Add columns of same email id in rails - ruby-on-rails

I have a table which has participant details
id name email level_id tournament_id
-------------------------------------------------------
20061 ABC abc#gmail.com 1 1
20062 xyz xyz#gmail.com 1 1
20063 ABC abc#gmail.com 2 1
20065 xyz xyz#gmail.com 2 1
and another table LevelScore
id participant_id level_id score
-----------------------------------------------------
1 20061 1 20
2 20062 2 30
3 20063 3 10
4 20061 4 30
5 20065 5 50
I want to add scores of same participants at different level, for eg: participant_id = 20061 & participant_id = 20063 are same participants participanting at different levels and i know that because they have same email.
Now i want to compute total score of participant i.e participant_score_level_1+participant_score_level_2+participant_score_level_3+participant_score_level_4 = Total score
How can i do it.

You can use participant.group(:email) for grouping the records according to the e-mail.

Try SELECT id, name, email, SUM(score) as score FROM participants GROUP BY email;. Then you can use result of the query to populate the new table.

You can group_by on email and in same query you can find sum of score also like below :
#participants = Participant.group(:email).select(:email, "SUM(score) as new_score")
Now When you try to create new table with unique email and sum of square you can do it like this :
#participants = Participant.group(:email).select(:email, "SUM(score) as new_score")
#participants.each do |participant|
Model.create(:email => participant.email, :sum_score => participant.new_score)
end

Related

Rails | Group by count of multiple columns

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

Fetching rows based on integer interval of a column

I am using rails 5.0.0 and postgresql
I have 3 tables namely orders, cart_items and products. The relation among them is as follows :
orders has_many cart_items
cart_item belongs_to product
Products table contains the price of the product.
What I want to do is fetch the number of orders between the price range of 2500 like orders which contain products worth between 0-2500, 2500-5000 and so on.
Thanks in advance.
The concept here is to group each orders by their total_price divided by 2500 (we're speaking about integer division here), so you will be able to group by their "sliced category".
Because:
300 / 2500 = 0
400 / 2500 = 0
2500 / 2500 = 1
3000 / 2500 = 1
3000 / 2500 = 1
4999 / 2500 = 1
5000 / 2500 = 2
etc. It's the result of this integer division that will create what I called earlier the "sliced category" (1 => 0-2500, 2 => 2500-5000, 3 => 5000-7500, etc). Since your total price may be decimal or floats, I "round" the value and cast them with ::integer.
The query can be something like this:
SELECT count(*), (sliced_2500_category + 1) * 2500 AS sliced_2500_group
FROM (
SELECT c.order_id, ROUND(SUM(price))::integer / 2500 AS sliced_2500_category
FROM cart_items c
INNER JOIN products p ON c.product_id = p.id
GROUP BY c.order_id
) orders_by_2500_category
GROUP BY sliced_2500_category;
Make sure your cart_items also belongs_to :orders
and product model has_many cart_items
I'm guessing you want to select the invoices/carts which are in the range of 0-2500 and so on..
Raw SQL:
SELECT order_id, sum(price)
FROM cart_items c INNER JOIN products p
ON c.product_id = p.id
GROUP_BY order_id
HAVING sum(price) BETWEEN 0 AND 2500
Required statement for controller:
CartItem.joins(:product)
.select(:order_id, 'sum(price)')
.group(:order_id)
.having('sum(price) BETWEEN 0 AND ?', params[:your_upper_limit_variable])

how to write active record query for selecting certain values in a column

I have a dogs table which has age as an attribute. Dogs with ages between 1 year -12 years are in one column and dogs under 1 year have different column. I want to be abel to select dogs that are between 8 - 12 years in age and count them. This is my query but it only selects one dog with certain age.
#checkup = Dog.where(age: 8).count
As suggested by Pavan you could use a range to create a BETWEEN query.
#checkup = Dog.where(age: 8..12).count
But this approach is still flawed since you have to periodically update all your records as time passes!
Instead use a Date column to record the birthdate of the dogs.
rails g migration AddBirthdateToDogs birthdate:date
rake db:migrate
Then you can select the dogs by:
Dog.where(birthdate: 8.years.ago..12.years.ago
Or if you want to be fancy you can create a class method:
class Dog < ActiveRecord::Base
# Select dogs by age
# #param [Range, Fixnum] age
# #return [ActiveRecord::Relation]
# #example
# Dog.aged(0)
# Dog.aged(1..2)
def self.aged(age)
if age.respond_to?(:map)
age = age.map do |x|
x.is_a?(Date)? x : x.years.ago
end
age = age.first..(age.last + 1.year)
elsif age.respond_to?(:year)
age = age.year.ago..(age + 1.year)
end
self.where(birthdate: ago)
end
end
If I understood correctly, the below should work
#checkup = Dog.where(age: 8..12).count
which returns the count of the dogs which are between 8-12.

How to get data from two different fields in sample table whether anyone of the field is NULL ?

I am using ruby 1.8.6 , rails 2.3.8.
Here , I have a problem with multiple combo box in Rails,
Product drop down list
Sku's drop down list ( depends on production selection )
Product tables fields are
id name
In Sku's tables fields are
id name product_id alias_id
Alias tables fields are
id name
For example I have Sku's tables data like below
id name product_id alias_id
1. 100-m 1 10
2. 10-ml 1 NULL
3. 150 1 2
4. 200-m 1 10
5. 300-m 1 10
in Controller I written query like,
#skus = Sku.all(:conditions => ["product_id = ? ",
params[:id]],:select=>"skus.id,
CASE when skus.alias_id IS NOT NULL then (SELECT alias.name FROM alias WHERE
alias.id = skus.alias_id group by alias.name) END AS 'skus_name'",
:order=>"skus_name" ,:include=>[:alias])
This query written output like,
id skus_name
1. 100gms
2. 10-ml
3. 150-ml
4. 100gms
5. 100gms
Can any one help me how to get the distinct results?
Thanks in advance
You can either call uniq on the #sku variable that is returned.
#skus = Sku.all(:conditions => ["product_id = ? ",
params[:id]],:select=>"skus.id,
CASE when skus.alias_id IS NOT NULL then (SELECT alias.name FROM alias WHERE
alias.id = skus.alias_id group by alias.name) END AS 'skus_name'",
:order=>"skus_name" ,:include=>[:alias]).uniq
This will perform the same DB select but get unique results in ruby.
The alternative is to use DISTINCT in the select
#skus = Sku.all(:conditions => ["product_id = ? ",
params[:id]],:select=>"skus.id,
CASE when skus.alias_id IS NOT NULL then (SELECT DISTINCT alias.name FROM alias WHERE
alias.id = skus.alias_id group by alias.name) END AS 'skus_name'",
:order=>"skus_name" ,:include=>[:alias])
This will only get unique results in the database.
I'd go with the second option as it should be quicker than doing uniq in ruby :)

Rails ActiveRecord distinct count of attribute greater than number of occurrences

I have a a table author_comments with a fields author_name, comment and brand id.
I would like to get the number (count) of records where the author has more than N (2) records for a given brand.
For example,
author_comments
author_name comment brand
joel "loves donuts" 1
joel "loves cookies" 1
joel "loves oranges" 1
fred "likes bananas" 2
fred "likes tacos" 2
fred "likes chips" 2
joe "thinks this is cool" 1
sally "goes to school" 1
sally "is smart" 1
sally "plays soccer" 1
In this case my query should return 2 for brand 1 and 1 for brand 2.
I'm interested in the best performing option here, not getting all the records from the db and sorting through them in ruby, I can do this. I'm looking for best way using active record constructs or sql.
Update:
Here is the SQL:
SELECT author_name, COUNT(*) AS author_comments
FROM fan_comments
WHERE brand_id =269998788
GROUP BY author_name
HAVING author_comments > 2;
Should I just do find_by_sql?
You can define the same query using active record constructions:
FanComments.all(
:select => 'author_name, count(*) as author_comments',
:group => 'author_name',
:having => 'author_comments > 2') # in rails 2
or:
FanComments.
select('author_name, count(*) as author_comments').
group('author_name').
having('author_comments > 2') # in rails 3
FanComment.group(:author_name).count

Resources