Calculate SUM based on a column from associated model - ruby-on-rails

I have a table called vehicles, which has a column called vehicle_id and price.
I have a table called sales, which references the vehicles table. It has the columns vehicle_id (references the vehicle table) and sale_status which can equal to 'sold' or 'loan'.
I am trying to calculate the total price of vehicles which equal to 'sold' in the sales table. Help is much appreciated!
This is what I have so far but it returns the wrong number.
vehicle.rb:
def self.vehicles_price_sum
vehicles_sold.sum(:price).to_f
end
def self.vehicles_sold
Vehicle.where(id: Sale.where(sale_status: 'Sold'))
end

You can try with a subquery (which is close to you solution, yet you need to provide a column name explicitly for in clause with select, otherwise sales' id column is going to be provided):
Vehicle.where(id: Sale.where(status: "Sold").select(:vehicle_id)).sum(:price)
# SELECT SUM(`vehicles`.`price`) FROM `vehicles` WHERE `vehicles`.`id` IN (SELECT `sales`.`vehicle_id` FROM `sales` WHERE `sales`.`sale_status` = 'Sold')

Related

Rails distinct values of a value returned by a method in model

Suppose I have an Employee model, there is a method in Employee model named def fixed
def fixed
return self.cached_fixed.to_f if self.cached_fixed.present?
return (self.current_salary && self.current_salary.fixed).to_f
end
end
def current_salary
return #current_salary if #current_salary
# #current_salary = self.employee_salaries.detect{|es| es.end_date == nil}
#current_salary = self.db_current_salary
return #current_salary
end
if the fixed were a column in employee table we could have just used Employee.distinct.select(:fixed) to pull the distinct values
is there a way if it's just a method not a field in table without loading all the employees.
I am expecting to get the unique values of a column from a table , but it may not be a column as in the above table
Not for an arbitrary method, no. But you start the query from the EmployeeSalary end and fetch only the column you care about in one query using select:
EmployeeSalary
.select(:fixed)
.join(:employee)
.where(end_date: nil)
This will run a select fixed from... query and return a list of EmployeeSalary objects, but all the fields that aren't listed in the select call will be nil. Assuming the constraint of only one salary record having end_date: nil, there will be one EmployeeSalary object per employee. You can add .distinct in the method chain if you want unique values.
I'm not sure how the caching logic fits into this question. You can apply caching logic on top of that list if you like, but doing one query like this is pretty fast.

Rails & Active Record: Get the average value of a column after grouping

I have a table user_keywords which :belongs_to :keywords. user_keywords has a column keyword_id, user_id, and relevance_score (float).
keyword table has a column 'name'.
I want to group all the user_keywords by their keyword_id.
I want to take the average of each of those groups' relevance_score
I want to sort groups by the highest relevance score
I want to return the name of the keyword from the groups, sorted by highest relevance score.
What is the most efficient way to query this?
try this:
Keyword.joins(:user_keywords)
.select('keywords.name, avg(user_keywords.relevance_score) as score')
.group('keywords.name')
.order('score DESC')
.map(&:name)

ActiveRecord - Getting the sum of user score

I have an "ITEMS" database made of; ITEM_ID, OWNER_ID and VALUE.
An owner can own unlimited items. An item can only have one owner.
And I have an "OWNER" database made of; ID, NAME
I want to find the NAMES of top 10 RICHEST (wealthier) people. How can I do that?
First, I need to sum the values of an owner_id; than compare that with others?
Here is what you can do :
Item.group(:owner_id) # grouping Items by owner id
.select("SUM(value) as sum") # summing values of each group
.order("sum DESC") # ordering resulting records by the sum value
.limit(10) # giving the top 10 records
It is kinda long solution but it worked for me:
toplist = []
all_owners = Owner.all
all_owners.each do |owner|
name = Owner.find(owner).name
owner_value = Item.where(owner_id: owner).sum(:value)
toplist << [owner_value,name]
end
#top10 = toplist.sort.last(10).reverse

Select all columns by a unique column value in Rails 3

In Rails 3, how do i select rows based on unique column values, i need to get all the columns for eg:
SELECT COUNT(DISTINCT date) FROM records
This only returns date column, but i want all the columns (name, date , age , created_at) columns not just the date.
Thanks for your help
The issue here is that, by definition, there may be multiple records with the same date. It requires logic in the user space to determine which of the multiple records with the unique date to use. Here's some code to get those rows:
Record.select("distinct date").each do |record|
records = Record.find_by_date record.date
puts records.count # do something with the records
end
If what you're really after is uniqueness among multiple columns, list all the relevant columns in the distinct query:
Record.select("distinct date, name, age, created_at").each do |record|
puts record.date
puts record.name
puts record.age
puts record.created_at
# ``record'' still represents multiple possible records
end
The fact that you are using distinct means that each "row" returned actually represents n rows, so the DB doesn't know which of the n rows to pull the remaining columns from. That's why it only returns the columns used in distinct. It can do no other...
I think this will help you
Model.find(:all, :select => 'DISTINCT name, date, age, created_at')
Please use it and let me know.
Model.group(:column)
For your case:
Record.group(:date)
This will return all your columns with no "date" repetitions.
For rails 3.2 and higher, Model.select('DISTINCT name, date, age, created_at')

Order table by grouping values in another table

I have a table of questions: title
Each question has answers, in another table: text, question_id
Each answer has votes, in another table: answer_id
I can ask for total votes with
question.votes.count
I have seen how to group the votes db at
http://guides.rubyonrails.org/active_record_querying.html#group
Vote.group("answer_id")
But I want to order my questions by votes. That is ordering an array from a table via the grouping of another table. Is that possible?
q=Question.last
q.answers.order_by_vote #How to do this?
I think my answer could be doing a scope on the answer model that makes the grouping on the subset of votes that belong to the question. Am I right?
Thank you.
First, I think that you mean table when you say DB (database). A table a structure inside a database that holds data for a specific model, for example (questions, votes and answers. In your case you have three tables.
Second, calling attr_accessible :answer_id does not make an attribute searchable by an index. It is searchable by this attribute regardless of whether or not you declare it accessible. It is not an index unless you specify it as an index in the database. attr_accessible means that the attribute can be set using mass-assignment, for example when you call update_attributes.
Finally, if you want to group by answer_id and order by the number of votes, you can do so with the following query:
Vote.select('count(id) as votes, answer_id').group('answer_id').order('votes DESC')
If you want to order by some other value than the one you are grouping by, you'll have to add that to your group as well. This ensures that you aren't getting arbitrary results for the second value. For example:
Vote.group('answer_id').group('column_1').order('column_1 DESC')
I just figured out a way to organize my links by vote count, using the sort method in my links view:
<% #user.links.sort { |a, b| b.votes.sum(:score) <=> a.votes.sum(:score) }.each do |link| %>
votes.sum(:score) grabs the number of votes a particular link has from the votes table.
hope that helps.

Resources