I have the following table:
category id date views
1 3 5-1-17 40
1 3 5-2-17 70
1 3 5-3-17 110
1 3 5-4-17 200
1 5 5-1-17 50
1 5 5-2-17 75
2 6 4-1-17 90
2 6 4-2-17 95
2 9 4-3-17 115
2 9 6-5-17 125
2 9 6-6-17 135
How do I sum the max views for each id by category?
The resulting pull should look like this:
category views
1 275
2 230
For category 1, the max views for id 3 is 200 and the max views for id 5 is 75. The sum for category 1 is thus 275.
For category 2, the max views for id 6 is 95 and the max views for id 9 is 135. The sum for category 2 is thus 230.
You can use two levels of aggregation:
select category, sum(max_views)
from (select category, id, max(views) as max_views
from t
group by category, id
) t
group by category;
You can also use row_number() here:
select category, sum(max_views)
from (select t.*,
row_number() over (partition by category, id, order by views desc) as seqnum
from t
) t
where seqnum = 1
group by category;
It would be interesting which is faster. I would vote on the double aggregation, but that might not always be true.
Related
I have 2 tables, first one is called members:
id name show
1 John 1
2 Wil 1
3 George 1
4 Chris 1
Second is called score:
id user_id score
1 1 90
2 1 70
3 2 55
4 3 30
5 3 40
6 3 100
7 4 30
user_id from score is the id of members.
What I want is to show a scorelist with unique members.id, ordered by score.score and order by the latest score.id.
I use the following code:
SELECT members.id, members.show, score.id, score.user_id, score.score FROM members
INNER JOIN score ON score.user_id = members.id
WHERE members.show = '1'
GROUP BY score.user_id
ORDER BY score.score DESC, score.id DESC
The output is not ordered by the latest score.id, but it does show only unique user_id's:
id user_id score
1 1 90
3 2 55
4 3 30
7 4 30
It should be like:
id user_id score
6 3 100
2 1 70
3 2 55
7 4 30
I hope you can help me
You could use:
with cte as (
select id,
user_id,
score,
row_number() over(partition by user_id order by id desc) as row_num
from score
) select cte.id,user_id,score
from cte
inner join members m on cte.user_id=m.id
where row_num=1
order by score desc;
Demo
If your MySQL server doesn't support windows function, use:
select s.id,s.user_id,s.score
from score s
inner join members m on s.user_id=m.id
where s.id in (select max(id) as id
from score
group by user_id
)
order by score desc;
Demo
I have a query like below, it is working fine but not optimized, since it takes 1.5 sec to run. How to make this to an optimized result?
select h.keyword_id,
( select count(DISTINCT(user_id)) from history where category_id = 6
and h.keyword_id=keyword_id group by keyword_id ) as cat_6,
( select count(DISTINCT(user_id)) from history where category_id = 7
and h.keyword_id = keyword_id group by keyword_id ) as cat_7
from
history h group by h.keyword_id
History table
his_id keyword_id category_id user_id
1 1 6 12
2 1 6 12
3 1 7 12
4 1 7 12
5 2 6 13
6 2 6 13
7 2 7 13
8 3 6 13
Result:
keyword_id cat_6 cat_7
1 2 2 (unique users)
2 2 1
3 1 0
You can rewrite your query like this:
select h.keyword_id,
count(distinct if(category_id = 6, user_id, null)) as cat_6,
count(distinct if(category_id = 7, user_id, null)) as cat_7
from
history h
group by h.keyword_id
Your desired result based on the sample data is by the way false. In each keyword_id there's always just one distinct user_id.
you can see the query in action in an sqlfiddle here
For more optimization, you'd have to post the result of show create table history and the output of explain <your_query>;
I have a table structured like this:
user_id saved_id
1 2
1 34
1 36
2 489
2 14
3 731
4 48
5 901
6 234
6 9
6 64
What I would like to do is first count how many saved ids each user has, and then group these results so that I know how often each total_saves occurs.
This is what I currently have:
SELECT user_id, count(*) as total_saves FROM table GROUP BY user_id ORDER BY total_saves DESC
Which gives me
user_id total_saves
1 3
6 3
2 2
3 1
4 1
5 1
What I would like to have is this:
total_saves count
3 2
2 1
1 3
Can't get my head around how to group the total_saves that I already have. I tried GROUP BY total_saves but that doesn't work.
Use two aggregations:
select total_saves, count(*) as cnt
from (select user_id, count(*) as total_saves
from t
group by user_id
) t
group by total_saves;
Use Subquery
select total_saves, count(total_saves) as count
from (select user_id, count(*) as total_saves
from table
group by user_id
) a
group by total_saves order by total_saves;
I have my data base like this
id project_id client_id price
1 1 1 200
2 2 1 123
3 2 1 100
4 1 1 87
5 1 1 143
6 1 1 100
7 3 3 123
8 3 3 99
9 4 3 86
10 4 3 43
11 4 3 145
12 4 3 155
Now here I want that it will sum the price columns with the same client_id.
For that I just made my query like this
Select `project_id`, SUM(`price`) FROM `table-name` GROUP BY `client_id`
This one is doing sum the price but I am getting only two project_id in the result. I want the result should be all the distinct project for the client id and the price will be summed for the group clients.
So can someone tell me how to do this? Any help and suggestions will be really appreciable. Thanks
You should not have "bare" column in a group by query that are not in the group by statement.
If you want the list of projects, you can get them in a list like this:
SELECT client_id, GROUP_CONCAT(project_id), SUM(price)
FROM table-name
GROUP BY client_id;
you only have two client that why you are getting only two record , you can group by two column,
Select `project_id`, SUM(`price`) FROM `table-name` GROUP BY `client_id`, `project_id`
I want to SUM two columns from two different database and output the highest value.
trying to figure it out since last 1day but no luck. can anyone please help?
Table 1
mid points
1 20
2 10
1 10
1 30
3 10
Table 2
mid points
1 20
2 10
1 10
2 20
1 10
3 10
so the total should be
mid points
1 100
2 40
3 20
output that i want highest total mid is 1 = 100
Try this untested query:
select mid , sum(points) from (
select mid,points from table1
union all
select mid,points from table2
) as table3
group by mid
order by sum(points) DESC
limit 1