SQL Server 2005 GROUP BY and COUNT query for each month - sql

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.

Related

How to count number of rows returned per month in oracle? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I am creating a feature for my application where I need to generate a report for the whole 2018.
I need to count all the tickets for 2018. Each ticket has a category.
For example:
Change of name.
Senior Citizen etc.
I need to count the number of change name tickets, senior citizen tickets for 2018 per month
I tried to to this but I can't seem to get the result that I want.
I can't seem to break down the count per month.
This is the query that I have so far:
SELECT SUBCATEGORY,COUNT(ticket_no)
FROM CNR_TICKET
WHERE date_created >= TO_DATE('1/01/2018','MM/DD/YYYY')
AND date_created <= TO_DATE('12/31/2018','MM/DD/YYYY')
GROUP BY SUBCATEGORY;
This is the columns I want to see:
CATEGORY | JAN | FEB | MARCH | APRIL | MAY | JNE | JUL | AUG | SEPT | OCT| NOV| DEC
SENIOR 2 5 20 50 1 11 23 4 1 2 4 6
COAN 23 55 22 55 6 2 12 23 12 12 5 89
Something like this :
SELECT
SUBCATEGORY,
count( distinct case when EXTRACT(month FROM date_created) = 1 then ticket_no else null end) as JAN,
count( distinct case when EXTRACT(month FROM date_created) = 2 then ticket_no else null end) as FEB,
count( distinct case when EXTRACT(month FROM date_created) = 3 then ticket_no else null end) as MARCH,
count( distinct case when EXTRACT(month FROM date_created) = 4 then ticket_no else null end) as APRIL,
count( distinct case when EXTRACT(month FROM date_created) = 5 then ticket_no else null end) as MAY,
count( distinct case when EXTRACT(month FROM date_created) = 6 then ticket_no else null end) as JNE,
count( distinct case when EXTRACT(month FROM date_created) = 7 then ticket_no else null end) as JUL,
count( distinct case when EXTRACT(month FROM date_created) = 8 then ticket_no else null end) as AUG,
count( distinct case when EXTRACT(month FROM date_created) = 9 then ticket_no else null end) as SEPT,
count( distinct case when EXTRACT(month FROM date_created) = 10 then ticket_no else null end) as OCT,
count( distinct case when EXTRACT(month FROM date_created) = 11 then ticket_no else null end) as NOV,
count( distinct case when EXTRACT(month FROM date_created) = 12 then ticket_no else null end) as DEC
FROM
CNR_TICKET
WHERE
date_created >= to_date('1/01/2018','MM/DD/YYYY') and
date_created <= to_date('12/31/2018','MM/DD/YYYY')
GROUP BY
SUBCATEGORY
you can change your WHERE clause using :
EXTRACT(year FROM date_created ) = 2018
You may try PIVOT statement
select * from (
select SUBCATEGORY, month(date_created) mon
from CNR_TICKET
where date_created >= to_date('1/01/2018','MM/DD/YYYY') and date_created <= to_date('12/31/2018','MM/DD/YYYY')
)
pivot (
count(*)
for mon
in ( 1 Jan, 2 Feb, 3 MARCH, 4 APRIL, 5 MAY, 6 JNE, 7 JUL, 8 AUG, 9 SEPT, 10 OCT, 11 NOV, 12 DEC )
)
you can use Pivot keyword by using for month for the pivoting query as
select *
from
(
select subcategory, to_char(date_created,'mm') as month
from cnr_ticket
where to_char(date_created,'yyyy')='2018'
)
pivot(
count(*)
for (month)
in ('01' as jan ,'02' as feb, '03' as mar,
'04' as apr ,'05' as may, '06' as jun,
'07' as jul ,'08' as aug, '09' as sep,
'10' as oct ,'11' as nov, '12' as dec
)
)
or using conditional aggregation
select subcategory,
sum(case when to_char(date_created,'mm') = '01' then 1 else 0 end) as jan,
sum(case when to_char(date_created,'mm') = '02' then 1 else 0 end) as feb,
sum(case when to_char(date_created,'mm') = '03' then 1 else 0 end) as mar,
sum(case when to_char(date_created,'mm') = '04' then 1 else 0 end) as apr,
sum(case when to_char(date_created,'mm') = '05' then 1 else 0 end) as may,
sum(case when to_char(date_created,'mm') = '06' then 1 else 0 end) as jun,
sum(case when to_char(date_created,'mm') = '07' then 1 else 0 end) as jul,
sum(case when to_char(date_created,'mm') = '08' then 1 else 0 end) as aug,
sum(case when to_char(date_created,'mm') = '09' then 1 else 0 end) as sep,
sum(case when to_char(date_created,'mm') = '10' then 1 else 0 end) as oct,
sum(case when to_char(date_created,'mm') = '11' then 1 else 0 end) as nov,
sum(case when to_char(date_created,'mm') = '12' then 1 else 0 end) as dec
from cnr_ticket
where to_char(date_created,'yyyy')='2018'
group by subcategory
Rextester Demo

SQL I want to get the following output

I have a sales table
Date_s sales_man product qty
1-Jan-18 xx 01 30
1-Jan-18 xx 01 20
1-Jan-18 xy 01 20
1-Feb-18 xz 02 10
5-Feb-18 xz 02 30
1-Feb-18 xx 01 10
1-Feb-18 xx 01 40
1-Mar-18 xy 03 20
I want to get the following output data format as
Product sales_man Jan Feb Mar
01 xx 50 10 0
01 xy 20 0 0
02 xx 0 0 0
02 xy 0 0 0
02 xz 0 0 0
03 xy 0 0 20
You can use aggregation. Something like this:
select product, salesperson,
sum(case when extract(month from dates) = 1 then qty else 0 end) as jan,
sum(case when extract(month from dates) = 2 then qty else 0 end) as feb
from t
group by product, salesperson;
This uses ANSI SQL date functions, because your database tag is not clear. Date operations can differ by database.
Also, when looking at data by month, typically, you want to take the year into account as well (by filtering or aggregating on the year).
If i got Your problem right, you can try:
SELECT * into #TempTable FROM
(select product, salesman, qty, FORMAT(Dates, 'MMM') as Months from sales
) AS s
PIVOT
(
SUM(qty)
FOR Months in (Jan, Feb)
) AS Pvt
select product, salesman, isnull(Jan, 0) as Jan, isnull(Feb, 0) as Feb from
#TempTable order by product
drop table #TempTable
If you can change your date format from '1-Jan-18' to '1-01-18', then you can do below way
check sql fiddle
http://sqlfiddle.com/#!9/6d3824/2
If you consider below date format
'1-01-18',
'1-01-18',
'1-02-18';
then you can do this query
select product, salesman,
sum(case when extract(month from dates) = 1 then qty else 0 end) as jan,
sum(case when extract(month from dates) = 2 then qty else 0 end) as feb
from sales
group by product, salesman;
Result
product salesman jan feb
1 xx 30 0
1 xz 0 20
2 xy 10 0
For all month
http://sqlfiddle.com/#!9/6d3824/9
for all do query like this,
select product, salesman,
sum(case when extract(month from dates) = 1 then qty else 0 end) as jan,
sum(case when extract(month from dates) = 2 then qty else 0 end) as feb,
sum(case when extract(month from dates) = 3 then qty else 0 end) as mar,
sum(case when extract(month from dates) = 4 then qty else 0 end) as apr,
sum(case when extract(month from dates) = 5 then qty else 0 end) as may,
sum(case when extract(month from dates) = 6 then qty else 0 end) as jun,
sum(case when extract(month from dates) = 7 then qty else 0 end) as jul,
sum(case when extract(month from dates) = 8 then qty else 0 end) as aug,
sum(case when extract(month from dates) = 9 then qty else 0 end) as sep,
sum(case when extract(month from dates) = 10 then qty else 0 end) as oct,
sum(case when extract(month from dates) = 11 then qty else 0 end) as nov,
sum(case when extract(month from dates) = 12 then qty else 0 end) as dece
from sales
group by product, salesman;
Result would be
product salesman jan feb mar apr may jun jul aug sep oct nov dece
1 xx 30 0 0 0 0 0 0 0 0 0 0 0
1 xz 0 20 0 0 0 0 0 0 0 0 0 0
2 xy 10 0 0 0 0 0 0 0 0 0 0 0

SQL - Calculate Customer's Percentage of Total Orders by Month

I'm practicing SQL on this site: https://www.w3schools.com/sql/trysqlserver.asp?filename=trysql_func_sqlserver_substring
, and am trying to calculate the % of total monthly orders by customer ID. So for example, if customer 10 had 3 orders in January, and there were 33 orders total in January, then customer 10's result in January would be 3/33 = 9.09%. I want each row to be a customer ID, and a column for each month.
Basically, I want to convert this:
Into this:
I can get the totals by month, but am having trouble getting the percentages.
I'm using this code:
SELECT d.CustomerID,
SUM(CASE WHEN Month = 01 THEN NumOrders ELSE 0 END) AS Jan,
SUM(CASE WHEN Month = 02 THEN NumOrders ELSE 0 END) AS Feb,
SUM(CASE WHEN Month = 03 THEN NumOrders ELSE 0 END) AS Mar,
SUM(CASE WHEN Month = 04 THEN NumOrders ELSE 0 END) AS Apr,
SUM(CASE WHEN Month = 05 THEN NumOrders ELSE 0 END) AS May,
SUM(CASE WHEN Month = 06 THEN NumOrders ELSE 0 END) AS Jun,
SUM(CASE WHEN Month = 07 THEN NumOrders ELSE 0 END) AS Jul,
SUM(CASE WHEN Month = 08 THEN NumOrders ELSE 0 END) AS Aug,
SUM(CASE WHEN Month = 09 THEN NumOrders ELSE 0 END) AS Sep,
SUM(CASE WHEN Month = 10 THEN NumOrders ELSE 0 END) AS Oct,
SUM(CASE WHEN Month = 11 THEN NumOrders ELSE 0 END) AS Nov,
SUM(CASE WHEN Month = 12 THEN NumOrders ELSE 0 END) AS [Dec],
SUM(NumOrders) AS Total
FROM(
SELECT CustomerID,
DATEPART(mm,OrderDate) AS Month,
COUNT(OrderID) AS NumOrders
FROM Orders
GROUP BY CustomerID,
DATEPART(mm,OrderDate)
) d
GROUP BY d.CustomerID
WITH ROLLUP
I've tried using this code like this to calculate the percentages, but am not getting it to work out.
SUM(CASE WHEN Month = 01 THEN NumOrders ELSE 0 END) / CAST( SUM(NumOrders) OVER (PARTITION BY Month) AS FLOAT) AS JanPct,
This is pretty basic in Excel, and seems like it should be in SQL too, so I feel like I'm missing something obvious.
Try this
Create table #tmp (CustId INT, Jan int, Feb Int, March int)
insert into #tmp VALUES
(10,4,3,5),
(11,3,1,7),
(12,6,2,6),
(13,5,4,4);
Select * from #tmp
select CustId,
CEILING(CAST(Jan As FLOAT)/CAST(SUM(Jan) OVER() AS FLOAT)*100) As Jan,
CEILING(CAST(Feb As FLOAT)/CAST(SUM(Feb) OVER() AS FLOAT)*100) As Feb,
CEILING(CAST(March As FLOAT)/CAST(SUM(March) OVER() AS FLOAT)*100) As March
from #tmp
drop table #tmp
if you want % symbol, convert to varchar and append %
Eg:
CONVERT(VARCHAR(5),CEILING(CAST(Jan As FLOAT)/CAST(SUM(Jan) OVER() AS FLOAT)*100))+'%'
I wasn't able to make rollup work with PIVOT, so here is the long solution.
DECLARE #t table(OrderId INT identity(1,1), OrderDate date, CustomerID INT)
INSERT #t values('2017-01-01', 1),('2017-01-01', 1),('2017-02-01', 1),('2017-01-01', 2)
;WITH CTE as
(
SELECT DISTINCT
CAST(ROUND(count(*) over(partition by CustomerID, Month(OrderDate))*100./ count(*)
over(partition by month(OrderDate)), 0) as INT) Pct,
Month(OrderDate) Mon,
CustomerID
FROM #t
)
SELECT
CustomerID,
SUM(CASE WHEN Mon = 1 THEN Pct ELSE 0 END) AS Jan,
SUM(CASE WHEN Mon = 2 THEN Pct ELSE 0 END) AS Feb,
SUM(CASE WHEN Mon = 3 THEN Pct ELSE 0 END) AS Mar,
SUM(CASE WHEN Mon = 4 THEN Pct ELSE 0 END) AS Apr,
SUM(CASE WHEN Mon = 5 THEN Pct ELSE 0 END) AS May,
SUM(CASE WHEN Mon = 6 THEN Pct ELSE 0 END) AS Jun,
SUM(CASE WHEN Mon = 7 THEN Pct ELSE 0 END) AS Jul,
SUM(CASE WHEN Mon = 8 THEN Pct ELSE 0 END) AS Aug,
SUM(CASE WHEN Mon = 9 THEN Pct ELSE 0 END) AS Sep,
SUM(CASE WHEN Mon = 10 THEN Pct ELSE 0 END) AS Oct,
SUM(CASE WHEN Mon = 11 THEN Pct ELSE 0 END) AS Nov,
SUM(CASE WHEN Mon = 12 THEN Pct ELSE 0 END) AS [Dec]
FROM CTE
GROUP BY ROLLUP (CustomerID)
Just Use below code instead of selecting COUNT(OrderID) AS NumOrders in your below subquery
CONVERT(numeric(10,2), count(Orderid) * 100.0/ (select count(Orderid) from [Orders])) as NumOrders

Select distinct count usage divided by month

I do have a table license_Usage which works like a log of the usage of licenses in a day
ID User license date
1 1 A 22/1/2015
2 1 A 23/1/2015
3 1 B 23/1/2015
4 1 A 24/1/2015
5 2 A 22/2/2015
6 2 A 23/2/2015
7 1 B 23/2/2015
Where I want it to return the count of licenses of the day of the month with most usage of licenses the result should look like:
User Jan Feb
1 2 1 ...
2 0 2
I know I can get the total of licenses in a month using this query:
SELECT vlu.[Userkey],
COUNT(CASE WHEN MONTH = 1 THEN 1 END) as JAN,
COUNT(CASE WHEN MONTH = 2 THEN 1 END) as FEB,
COUNT(CASE WHEN MONTH = 3 THEN 1 END) as MAR,
COUNT(CASE WHEN MONTH = 4 THEN 1 END) as APR,
COUNT(CASE WHEN MONTH = 5 THEN 1 END) as MAY,
COUNT(CASE WHEN MONTH = 6 THEN 1 END) as JUN,
COUNT(CASE WHEN MONTH = 7 THEN 1 END) as JUL,
COUNT(CASE WHEN MONTH = 8 THEN 1 END) as AUG,
COUNT(CASE WHEN MONTH = 9 THEN 1 END) as SEP,
COUNT(CASE WHEN MONTH = 10 THEN 1 END) as OCT,
COUNT(CASE WHEN MONTH = 11 THEN 1 END) as NOV,
COUNT(CASE WHEN MONTH = 12 THEN 1 END) as DEC
FROM license_usage vlu
CROSS APPLY (SELECT MONTH(vlu.EndDate)) AS CA(Month)
WHERE vlu.[EndDate] >='2015-01-01'
AND vlu.[EndDate] < '2016-01-01'
GROUP BY vlu.[Userkey]
How can I get it to return my results?
Example:
http://sqlfiddle.com/#!3/be0b4/1
Got it by using distinct on the Count (*)
select umd.pbrUserkey,
max(case when mm = 1 then cnt else 0 end) as Jan,
max(case when mm = 2 then cnt else 0 end) as Feb,
max(case when mm = 3 then cnt else 0 end) as Mar,
max(case when mm = 4 then cnt else 0 end) as Apr,
max(case when mm = 5 then cnt else 0 end) as May
from (select vluk.pbrUserkey, month(vluk.EndDate) as mm, day(vluk.EndDate) as dd,
count(distinct vluk.idPackage) as cnt
from [license_usage] as vluk
where vluk.[EndDate] >= '2015-01-01' AND vluk.[EndDate] < '2016-01-01'
group by vluk.Userkey, month(vluk.EndDate), day(vluk.EndDate)
) umd
group by umd.Userkey;
If I understand correctly, you want the maximum by day usage per month for each user. The basic data you want is:
select UserKey, month(license_usage) as mm, day(license_usage) as dd,
count(distinct license) as cnt
from license_usage vlu
where vlu.EndDate] >= '2015-01-01' and vlu.EndDate < '2016-01-01'
group by UserKey, month(license_usage), day(license_usage);
Then you can pivot this in several ways, such as using conditional aggregation:
select UserKey,
max(case when mm = 1 then cnt else 0 end) as Jan,
. . .
from (select UserKey, month(license_usage) as mm, day(license_usage) as dd,
count(distinct license) as cnt
from license_usage vlu
where vlu.EndDate] >= '2015-01-01' AND vlu.EndDate < '2016-01-01'
group by UserKey, month(license_usage), day(license_usage)
) umd
group by UserKey;
CROSS APPLY is an interesting approach, but I can't think of a simpler way to get this information.

Count no of month appear in Single column in SQL

Here in one column dates are in random order. I want to build query where it will count all the months how many times it appears.
SQL Table :-
EMP_table_date
10/26/2014
10/26/2014
10/24/2014
11/26/2014
11/26/2014
11/23/2014
12/26/2014
12/26/2014
Expected Output : -
Oct | Nov | Dec
3 | 3 | 2
Note:
Only single column mentioned above
Using Oracle 11G Database
select count(case when extract(month from emp_table_date) = 1 then 1 end) as jan,
count(case when extract(month from emp_table_date) = 2 then 1 end) as feb,
count(case when extract(month from emp_table_date) = 3 then 1 end) as mar,
count(case when extract(month from emp_table_date) = 4 then 1 end) as april,
count(case when extract(month from emp_table_date) = 5 then 1 end) as may,
count(case when extract(month from emp_table_date) = 6 then 1 end) as jun,
count(case when extract(month from emp_table_date) = 7 then 1 end) as jul,
count(case when extract(month from emp_table_date) = 8 then 1 end) as aug,
count(case when extract(month from emp_table_date) = 9 then 1 end) as sep,
count(case when extract(month from emp_table_date) = 10 then 1 end) as oct,
count(case when extract(month from emp_table_date) = 11 then 1 end) as nov,
count(case when extract(month from emp_table_date) = 12 then 1 end) as december
from emp_table;
SELECT TRUNC(emp_table_date,'MON') as "MON",
COUNT(emp_table_date) as "CNT"
FROM emp_table
GROUP BY TRUNC(emp_table_date,'MON');
This will return the count of each month in rows. Use standard PIVOT to convert it into columns.