SQL Server dense_rank with sum - sql

I have a query,which is not returning proper result,
i want my query to return total of score for same user_id, so that each user_id will have only one record with sum of all of its score.
My query is this:
SELECT
DENSE_RANK() OVER (ORDER BY score DESC) AS rank,
user_id,
SUM(score) AS total_score
FROM
account_game
GROUP BY
user_id, score
ORDER BY
rank ASC
Query output is :
rank user_id total_score
1 2 4837
2 1 600
2 6 600
3 1 30
4 1 20
There should be three records with user_id 1,2,6
Expected result should be
rank user_id total_score
-------------------------
1 2 4837
2 6 700
3 1 650
Please suggest

As StuartLC commented, you can just remove the score from your GROUP BY and all should be fine:
SELECT DENSE_RANK() OVER (Order by SUM(score) DESC) AS rank,
user_id,
SUM(score) as total_score
FROM
account_game
GROUP BY user_id
ORDER BY rank ASC

Related

How to return multiple columns when using "group by"?

Suppose I have the following data:
itemID catID score age
1 1 9 5
2 1 10 7
3 1 5 10
4 2 18 11
5 2 15 15
I want to return the age column, for the maximum score of each category:
catID score age
1 10 7
2 18 11
I have the following query:
select catID, max(score)
from items
group by catID
But I don't know how to include the age column as well.
What you're after here isn't aggregation on score but the details of the person with the highest score. You can use a CTE and ROW_NUMBER to achieve this:
WITH CTE AS(
SELECT catID,
score,
age,
ROW_NUMBER() OVER (PARTITION BY catID ORDER BY score DESC) AS RN
FROM items)
SELECT catID,
score,
age
FROM CTE
WHERE RN = 1;
If multiple people could have the same score, and you want to return them all, replace ROW_NUMBER with DENSE_RANK.
You need a join on the subqiery for amx score
select i.catID, i.score, i.age
from items i
INNER JOIN (
select catID, max(score) score
from items
group by catID
) t on t.catID = i.CatID and t.score = i.score

SQL : Return joint most frequent values from a column

I have the following table named customerOrders.
ID user order
1 1 2
2 1 3
3 1 1
4 2 1
5 1 5
6 2 4
7 3 1
8 6 2
9 2 2
10 2 3
I want to return to users with most orders. Currently, I have the following QUERY:
SELECT user, COUNT(user) AS UsersWithMostOrders
FROM customerOrders
GROUP BY user
ORDER BY UsersWithMostOrders DESC;
This returns me all the values grouped by total orders like.
user UsersWithMostOrders
1 4
2 4
3 1
6 1
I only want to return the users with most orders. In my case that would be user 1 and 2 since both of them have 4 orders. If I use TOP 1 or LIMIT, it will only return the first user. If I use TOP 2, it will only work in this scenario, it will return invalid data when top two users have different count of orders.
Required Result
user UsersWithMostOrders
1 4
2 4
You can use TOP 1 WITH TIES:
SELECT TOP 1 WITH TIES
[user], COUNT(*) AS UsersWithMostOrders
FROM customerOrders
GROUP BY [user]
ORDER BY UsersWithMostOrders DESC;
See the demo.
Results:
> user | UsersWithMostOrders
> ---: | ------------------:
> 1 | 4
> 2 | 4
Option 1
Should work with most versions of SQL.
select *
from (
select *,
rank() over(order by numOrders desc) as rrank
from (
select `user`, count(*) as numOrders
from customerOrders
group by `user`
) summed
) ranked
where rrank = 1
Play around with the code here
Option 2
If your version of SQL allows window functions (with), here is a much more readable solution which does the same thing
with summed as (
select `user`, count(*) as numOrders
from customerOrders
group by `user`
),
ranked as (
select *,
rank() over(order by numOrders desc) as rrank
from summed
)
select *
from ranked
where rrank = 1
Play around with the code here
You can use a CTE to attain this Req:
;WITH CTE AS(
SELECT [user], COUNT(user) AS UsersWithMostOrders
FROM #T
GROUP BY [user])
SELECT M.* from CTE M
INNER JOIN ( SELECT
MAX(UsersWithMostOrders) AS MaximumOrders FROM CTE) S ON
M.UsersWithMostOrders=S.MaximumOrders
Below Oracle Query can help:
WITH test_table AS
(
SELECT user, COUNT(order) AS total_order , DENSE_RANK() OVER (ORDER BY
total_order desc) AS rank_orders FROM customerOrders
GROUP BY user
)
select * from test_table where rank_orders = 1

Get max count with lead name

My dataset name bollywood.csv:
This is my data. I need the actors who have the most lead roles in movies.
I Need the name of the lead actors and the number of films in which they have lead.
My code is:
select lead, count(*) as nos from bollywood group by lead order by nos desc;
And the result is:
Amitabh 3
Akshay 3
John 3
Riteish 2
Shahrukh 2
Sunny 2
Emraan 2
Katrina 2
Nawazuddin 2
Tiger 2
Sharman 2
Manoj 2
Vidya 1
Tusshar 1
Tannishtha 1
Sushant 1
SunnyDeol 1
Sonam 1
Sonakshi 1
Siddarth 1
Shahid 1
Sandeep 1
Salman 1
If you want all actors with most lead roles (possibly multiple records):
select lead, count(*) as nos
from bollywood
group by lead
having count(*) =
(select max(cnt) from
(select lead, count(*) cnt
from bollywood
group by lead ) tblBolly )
Use rownum pseudocolumn with order by (oracle).
select from (
select lead, count(*) as nos
from bollywood
group by lead
order by lead desc
)
where rownum = 1
Use window functions:
select lead, cnt
from (select lead, count(*) as cnt,
rank() over (order by count(*) desc) as rnk
from bollywood
group by lead
) b
where rnk = 1;

Get MAX value of each record in group by query

I have a query in SQL looks like that:
select fldCustomer, fldTerminal, COUNT(fldbill)
from tblDataBills
group by fldCustomer, fldTerminal
order by fldCustomer
results looks like:
fldCustomer fldTerminal (number of bills)
0 1 19086
0 2 10
0 5 236
1 1 472
1 5 3
1 500 19
2 1 292
2 500 22
how can i get the MAX count of each customer so i get results like
0 1 19086
1 1 472
2 1 292
Thanks in advance!
Use a subquery with row_number():
select fldCustomer, fldTerminal, cnt
from (select fldCustomer, fldTerminal, COUNT(*) as cnt,
row_number() over (partition by fldCustomer order by count(*) desc) as seqnum
from tblDataBills
group by fldCustomer, fldTerminal
) db
where seqnum = 1
order by fldCustomer ;
Note that in the event of ties, this will arbitrarily return one of the rows. If you want all of them, then use rank() or dense_rank().
This might require a little trickery with the RANK() function
SELECT fldCustomer, fldTerminal, [(number of bills)]
FROM (
SELECT fldCustomer, fldTerminal, COUNT(fldbill) [(number of bills)],
RANK() OVER (PARTITION BY fldCustomer ORDER BY COUNT(fldbill) DESC) Ranking
FROM tblDataBills
GROUP BY fldCustomer, fldTerminal
) a
WHERE Ranking = 1

Oracle Nested Grouping

The question is: For each day, list the User ID who has read the most number of messages.
user_id msgID read_date
1 1 10
1 2 10
2 2 10
2 2 23
3 2 23
I believe the date is an outer group and user_id is an inner group, but how to do group nesting in sql? Or somehow avoid this?
This is a task for a Window Function:
select *
from
(
select user_id, read_date, count(*) as cnt,
rank()
over (partition by read_date -- each day
order by count(*) desc) as rnk -- maximum number
from tab
group by user_id, read_date
) dt
where rnk = 1
This might return multiple users for one with the same maximum count, if you want just one (randomly) switch to ROW_NUMBER
select user_id
from
(
select user_id,count(msgID)
from table
group by read_date
)
where rownum <= 1;