I have a SQL Server 2005 table named Rentals
:
RentalID
Book
Date
I want to return, using a query, for each book, how many rentals were in each month for a given year.
The results should look something like this:
+--------------------------------+-----+-----+-----+
| Book | Jan | Feb | Mar |
+--------------------------------+-----+-----+-----+
| Isaac Asimov - Foundation | 2 | 5 | 3 |
| H.G. Wells - War of the Worlds | 4 | 3 | 1 |
| Frank Herbert - Dune | 7 | 4 | 6 |
+--------------------------------+-----+-----+-----+
My query so far:
SELECT
Book,
(SELECT COUNT(*) FROM Rentals WHERE month(Date)=1 AND year(Date)=2011),
(SELECT COUNT(*) FROM Rentals WHERE month(Date)=2 AND year(Date)=2011),
(SELECT COUNT(*) FROM Rentals WHERE month(Date)=3 AND year(Date)=2011),
(SELECT COUNT(*) FROM Rentals WHERE month(Date)=4 AND year(Date)=2011),
(SELECT COUNT(*) FROM Rentals WHERE month(Date)=5 AND year(Date)=2011),
(SELECT COUNT(*) FROM Rentals WHERE month(Date)=6 AND year(Date)=2011),
(SELECT COUNT(*) FROM Rentals WHERE month(Date)=7 AND year(Date)=2011),
(SELECT COUNT(*) FROM Rentals WHERE month(Date)=8 AND year(Date)=2011),
(SELECT COUNT(*) FROM Rentals WHERE month(Date)=9 AND year(Date)=2011),
(SELECT COUNT(*) FROM Rentals WHERE month(Date)=10 AND year(Date)=2011),
(SELECT COUNT(*) FROM Rentals WHERE month(Date)=11 AND year(Date)=2011),
(SELECT COUNT(*) FROM Rentals WHERE month(Date)=12 AND year(Date)=2011)
FROM Rentals
GROUP BY Book
This can be written much simpler by using a CASE expression inside of an aggregate function. This process is called PIVOT:
select book,
sum(case when month(Date) = 1 then 1 else 0 end) Jan,
sum(case when month(Date) = 2 then 1 else 0 end) Feb,
sum(case when month(Date) = 3 then 1 else 0 end) Mar,
sum(case when month(Date) = 4 then 1 else 0 end) Apr,
sum(case when month(Date) = 5 then 1 else 0 end) May,
sum(case when month(Date) = 6 then 1 else 0 end) Jun,
sum(case when month(Date) = 7 then 1 else 0 end) Jul,
sum(case when month(Date) = 8 then 1 else 0 end) Aug,
sum(case when month(Date) = 9 then 1 else 0 end) Sep,
sum(case when month(Date) = 10 then 1 else 0 end) Oct,
sum(case when month(Date) = 11 then 1 else 0 end) Nov,
sum(case when month(Date) = 12 then 1 else 0 end) Dec
from Rentals
where year(date) = 2011
group by book;
See SQL Fiddle with Demo . Instead of querying the table multiple times for each column, you use conditional aggregation to get the count for each book during the month and year.
If you use pivot the code is much easier to maintain,
SELECT
BOOK,
[1] as Jan ,
[2] as Feb,
[3] as Mar,
[4] as Apr,
[5] as May,
[6] as Jun,
[7] as Jul,
[8] as Aug,
[9] as Sep,
[10] as Oct,
[11] as Nov,
[12] as Dec
FROM
(
SELECT
BOOK ,
DATEPART(MONTH,[DATE]) AS PER
FROM
Rentals
WHERE
DATEPART(YEAR,[DATE]) = 2014
) AS P PIVOT
(
COUNT(PER) FOR PER IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])
) AS DATA
Simple.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.