2 tables: memberships and week_scores
Membership has_many :week_scores
WeekScore belongs_to :membership
Every membership has 16 week_scores
Every week_score table has a score column that has an integer from 0 to 20.
So just to be clear all memberships have 16 week_scores and I want to display a leaderboard table of all members of the group sorted by the total score of all their 16 week_scores tables.
It should look something like this
Username | Score
David | 114
Rick | 97
Mike | 95
...
The score column should be a sum of all the week_scores one user has so in case of David it was
week_score.score 1: 15
week_score.score 2: 12
week_score.score 3: 14
...
week_score.score 16: 9
total: 114
If the name of the post is not good let me know.
One way of doing this is with an subselect:
subselect = "SELECT SUM(score) FROM week_scores WHERE membership_id=memberships.id"
#memberships = Membership.
select("memberships.*, (#{subselect}) AS total_score").
order("total_score DESC")
The additional column specified in the select clause (total_score) will be available on the returned membership instances as if it were a “real” attribute, so calling something like #memberships.first.total_score will work.
(Note that I extracted the subselect into a separate variable only to make the code more readable, it is of course also possible to have it inline instead.)
Related
How can I get unique values from column in the table? For example, I have this Products table:
user_id number
1 900
1 400
2 100
2 300
3 200
Here I used....
like so
Post.order(number: :desc).limit(3).each do |p| > I got here
user_id number
1 900
1 400
2 300
like so
Here I want "user_id" not to overlap. like this
f
user_id number
1 900
2 300
3 200
As deepak adviced, you might use distinct.
However, I guess you need to get maximum value from all records with the same user_id? Then you need to use sql to group values by user_id and selecting max from it. In Rails that might be like this. I can't tell you that it will work for sure because don't remember the output, believe it's array of hashes, it might throw the error that you're not using some other field:
Post.group(:user_id).max(:value)
it's SQL equalent:
SELECT user_id, MAX(value) FROM posts GROUP BY user_id
I have model named Group which has many users,
Group contains the fields for min_age and max_age describing the user's with minimum age and maximum age.
Each user has its settings where sets preferred age group like 18 to 25
When a user searches for groups than I have order groups with age b/w 18 to 25 first and than rest
I am doing it with 2 queries like
groups = Group.where("min_age >=? AND max_age <=?", setting.min_age, setting.max_age)
+ Group.where("min_age <? OR max_age >?", setting.min_age, setting.max_age)
It worked but thing is I have too many other filters and I want cut short number of queries.
Is it possible to do this in single query?
You can do that by ordering matching records before records that do not match:
Group.order("CASE WHEN min_age >= #{setting.min_age} AND max_age <= #{settings.max_age} then 1 else 2 end")
See: SQL CASE statement.
I have two tables joined via third in a many-to-many relationship. To simplify:
Table A
ID-A (int)
Name (varchar)
Score (numeric)
Table B
ID-B (int)
Name (varchar)
Table AB
ID-AB (int)
A (foreign key ID-A)
B (foreign key ID-B)
What I want is to display the B-Name and a sum of the "Score" values of all the As belonging to the given B. However, the following code:
WITH "Data" AS(
SELECT "B."."Name" As "BName", "A"."Name", "Score"
FROM "AB"
LEFT OUTER JOIN "A" ON "AB"."A" = "A"."ID-A"
LEFT OUTER JOIN "B" ON "AB"."B" = "B"."ID-B")
SELECT "BName", SUM("Score") AS "Total"
FROM "Data"
GROUP BY "Name", "Score"
ORDER BY "Total" DESC
The results display several rows for every "BName" with the "score" divided into semingly random increments between these rows. For example, if the desired result for Johnny is 12 and for April it's 25, the query may shows something like:
Johnny | 7
Johnny | 3
Johnny | 2
April | 19
April | 5
April | 1
etc.
Even after trying to nest the query and doing another SELECT with SUM("Score"), the results are the same. I'm not sure what I'm doing wrong?
Remove Score from the GROUP BY clause:
SELECT BName, SUM(Score) AS Total
FROM Data
GROUP BY BName
ORDER BY Total DESC;
The purpose of your query is to summarize by name, so name alone should appear in the GROUP BY clause. By also including the score, you will get a record in the output for each unique name/score combination.
Okay, I figured out my problem. Indeed, I had to GROUP BY "Name" only, but Firebird I thought wasn't letting me do that. Turns out it was just a typo. Oops.
Model Material & Manager is many to many relationship,
this means Material needs to be checked by many managers,managers check many materials.
ManageMaterial is join table with attributes
material_id
manager_id
I load some data into join table like this
id manager_id material_id
---------- ---------- -----------
1 6 52
2 8 52
3 2 12
4 5 12
Now I want to show what materials are being checked, in this example I just want one item with material_id = 52, but if I do #items = ManageMaterial.all , it will return two items.
How to solve this problem?
If you want to get ManageMaterials without duplication:
#items = ManageMaterial.select("DISTINCT(material_id)")
If you want a single ManageMaterial with material_id:
#items = ManageMaterial.find_by_material_id(52)
Ruby 2.1.5
Rails 4.2.1
My model is contributions, with the following fields:
event, contributor, date, amount
The table would have something like this:
earth_day, joe, 2014-04-14, 400
earth_day, joe, 2015-05-19, 400
lung_day, joe, 2015-05-20, 800
earth_day, john, 2015-05-19, 600
lung_day, john, 2014-04-18, 900
lung_day, john, 2015-05-21, 900
I have built an index view that shows all these fields and I implemented code to sort (and reverse order) by clicking on the column titles in the Index view.
What I would to do is have the Index view displayed like this:
Event Contributor Total Rank
Where event is only listed once per contributor and the total is sum of all contributions for this event by the contributor and rank is how this contributor ranks relative to everyone else for this particular event.
I am toying with having a separate table where only a running tally is kept for each event/contributor and a piece of code to compute rank and re-insert it in the table, then use that table to drive views.
Can you think of a better approach?
Keeping a running tally is a fine option. Writes will slow down, but reads will be fast.
Another way is to create a database view, if you are using postgresql, something like:
-- Your table structure and data
create table whatever_table (event text, contributor text, amount int);
insert into whatever_table values ('e1', 'joe', 1);
insert into whatever_table values ('e2', 'joe', 1);
insert into whatever_table values ('e1', 'jim', 0);
insert into whatever_table values ('e1', 'joe', 1);
insert into whatever_table values ('e1', 'bob', 1);
-- Your view
create view event_summary as (
select
event,
contributor,
sum(amount) as total,
rank() over (order by sum(amount) desc) as rank
from whatever_table
group by event, contributor
);
-- Using the view
select * from event_summary order by rank;
event | contributor | total | rank
-------+-------------+-------+------
e1 | joe | 2 | 1
e1 | bob | 1 | 2
e2 | joe | 1 | 2
e1 | jim | 0 | 4
(4 rows)
Then you have an ActiveRecord class like:
class EventSummary < ActiveRecord::Base
self.table_name = :event_summary
end
and you can do stuff like EventSummary.order(rank: :desc) and so on. This won't slow down writes, but reads will be a little slower, depending on how much data you are working with.
Postgresql also has support for materialized views, which could give you the best of both worlds, assuming you can have a little bit of lag between when the data is entered and when the summary table is updated.