Rails | Group by count of multiple columns - ruby-on-rails

I have a Country model with name, school and branch columns.
I want to find out the unique number of schools and branches in a country.
I expect the result to be in this format:
{"India" => [25, 100]}
//{Country => [No.of unique schools, No.of unique branches]}
I want to calculate this value once in the controller (instead of doing something like below in the view).
Country.all.each do |country|
cs = Country.where(country: country).uniq.pluck(:school).count
cb = Country.where(country: country).uniq.pluck(:branch).count
end
I am able to group one column by count like this
Country.group(:school).order('count(school) desc').count
// {"India"=>31, "USA"=> 50 }
How can I do the same on multiple columns?
Thanks in advance :)

Related

Calculate SUM based on a column from associated model

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')

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')

How to copy a (Active)record between tables, partially?

In two tables mapped to ActiveRecord with unknown number of identical columns, e.g.:
Table A Table B
--------- ---------
id id
name name
age email
email is_member
How can I (elegantly) copy all identical attributes from a record of Table A to a record of Table B, except the id attribute?
For the example tables above, name and email fields should be copied.
Try this:
Get intersection of the columns between TableA and TableB
columns = (TableA.column_names & TableB.column_names) - ["id"]
Now iterate through TableA rows and create the TableB rows.
TableB.create( TableA.all(:select => columns.join(",") ).map(&:attributes) )
Edit: Copying one record:
table_a_record = TableA.first(:select => columns.join(","), :conditions => [...])
TableB.create( table_a_record.attributes)
Migt consider using a union function on the acitverecord attributes hash between the 2 tables. It's not a complete answer but may help

Resources