Reputation: 9
Let's say I have a table with the following schema:
User_id | Rating | Movie_id | Movie_Popularity
1 2 34 100
1 1 36 120
1 2 39 110
2 3 34 105
What I would like is for each user find his max and his min rating and in case of a tie select the movie that has the highest popularity(suppose these are all distinct).
In this example the result would be:
User_id | Max_rating | Min_rating | Max_rating_movie_id | Min_rating_movie_id
1 2 1 39 36
2 3 3 34 34
I have tried sorting this table with both rating and movie popularity but I am able to extract only the max or the min value.
How could this be done using sql?
Any advice would be helpful.
Thanks in advance
Upvotes: 0
Views: 302
Reputation: 164194
There is no need for subqueries.
You can do it with window functions MIN()
, MAX()
and FIRST_VALUE()
:
SELECT DISTINCT User_id,
MAX(Rating) OVER (PARTITION BY User_id) Max_rating,
MIN(Rating) OVER (PARTITION BY User_id) Min_rating,
FIRST_VALUE(Movie_id) OVER (PARTITION BY User_id ORDER BY Rating DESC, Movie_Popularity DESC) Max_rating_movie_id,
FIRST_VALUE(Movie_id) OVER (PARTITION BY User_id ORDER BY Rating, Movie_Popularity DESC) Min_rating_movie_id
FROM tablename
See the demo.
Results:
User_id | Max_rating | Min_rating | Max_rating_movie_id | Min_rating_movie_id |
---|---|---|---|---|
1 | 2 | 1 | 39 | 36 |
2 | 3 | 3 | 34 | 34 |
Upvotes: 1
Reputation: 1271003
One method uses window functions with aggregation:
select user_id, max(Movie_Popularity), min(Movie_Popularity),
max(case when seqnum_desc = 1 then movie_id end),
max(case when seqnum_asc = 1 then movie_id end)
from (select t.*,
row_number() over (partition by user_id order by Movie_Popularity asc) as seqnum_asc,
row_number() over (partition by user_id order by Movie_Popularity desc) as seqnum_desc
from t
) t
group by user_id;
Upvotes: 1
Reputation: 34
Hi, you can use row_number() over (partition by .. order by ...asc) .
This a query sample:
Select user_id, movie_id, row_number() over (partition by user_id order by rating desc) as max_rating, row_number() over (partition by user_id order by rating asc) as min_rating
Then you can use it as a sub query & select by where on max_rating & min_rating equals to 1.
Upvotes: 1