I'm trying to work out the SQL to list the top 5 rentals for each month on MySQL or SQL Server. The database is the Sakila Sample database and the table is rental. Here are the first several rows in my database client (Navicat Premium):
I'd like the take the month from the rental_date field.
Each film has a unique inventory_id.
So far I've got this:
SELECT
MONTH( rental_date ) AS month,
inventory_id,
COUNT ( inventory_id ) AS no_of_rentals
FROM
rental
GROUP BY
MONTH ( rental_date ),
inventory_id
HAVING
COUNT ( inventory_id ) > 1
ORDER BY
MONTH ( rental_date ),
inventory_id;
Unfortunately, that returns all films with more than one rental per month, which is not what I want.
I'd like to see something more like:
month inventory_id no_of_rentals
_________________________________
April 367 5
April 98 4
(3 more rows)
May 144 5
May 32 5
(3 more rows)
etc...
Bonus points if you can get the film title!
Thanks!
Rob
UPDATE:
Thanks to Dominique Boucher for the answer.
Here's my finished query:
WITH cte AS (
SELECT
MONTH(rental_date) rental_month_no,
DATENAME(month, rental_date) rental_month,
inventory_id,
COUNT( inventory_id ) no_of_rental,
ROW_NUMBER( ) OVER ( PARTITION BY MONTH(rental_date) ORDER BY COUNT( inventory_id ) DESC) Rank
FROM
rental
GROUP BY
MONTH(rental_date),
DATENAME(month, rental_date),
inventory_id
HAVING COUNT( inventory_id ) > 1
)
SELECT
rental_month,
cte.inventory_id,
title,
no_of_rental,
rank
FROM
cte
JOIN inventory ON cte.inventory_id = inventory.inventory_id
JOIN film ON inventory.film_id = film.film_id
WHERE
Rank < 6
ORDER BY rental_month_no, no_of_rental DESC;
I added code to fetch the titles and limited results to films that were rented more than once in a month.
Here are the results in Navicat:
Best Answer
Use pretty much the same script in a CTE but add the row number (partition by month). This will return all rows with a row number in front, reseting at 1 for every month. Then you can just issue your query with a "where rn <=5" and that will make it.
Here's an example just to give you a starting point: