Pivot and get count of rows in each cell? - sql

The following query gives me the year and month_num of each support ticket.
SELECT STRFTIME_UTC_USEC(created_at, '%Y') AS year,
STRFTIME_UTC_USEC(created_at, '%m') AS month_num
FROM zendesk.zendesk
I want to pivot the year values and show the COUNT(*) of all source rows in each cell, like this:
2014 2015 2016
01 5 ... ...
02 8
03 12
04 22
05 30
06 15
07 10
08 9
09 ...
10
11
12
How can I do this?

You can use conditional aggregation:
SELECT STRFTIME_UTC_USEC(created_at, '%m') AS month_num,
SUM(CASE WHEN STRFTIME_UTC_USEC(created_at, '%Y') = '2014' then 1 else 0 end) as cnt_2014,
SUM(CASE WHEN STRFTIME_UTC_USEC(created_at, '%Y') = '2015' then 1 else 0 end) as cnt_2015,
SUM(CASE WHEN STRFTIME_UTC_USEC(created_at, '%Y') = '2016' then 1 else 0 end) as cnt_2016
FROM zendesk.zendesk
GROUP BY month_num;

SELECT
month_num,
MIN(CASE WHEN [year] = '2014' THEN cnt END) AS year_2014,
MIN(CASE WHEN [year] = '2015' THEN cnt END) AS year_2015,
MIN(CASE WHEN [year] = '2016' THEN cnt END) AS year_2016
FROM (
SELECT
STRFTIME_UTC_USEC(created_at, '%Y') AS [year],
STRFTIME_UTC_USEC(created_at, '%m') AS month_num,
COUNT(*) AS cnt
FROM zendesk.zendesk
GROUP BY 1,2
)
GROUP BY 1

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 - 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

Is it possible to Count by diffrent condition in one query?

I have a Shipments table which basicly contains Shipments data with dates
id is integer
dateshipped is date
id dateshipped
1 1-JAN-16
2 1-JAN-16
3 3-FEB-16
4 9-FEB-16
I want to write a query which count all shipments based on Months.
What I should get is:
Jan Feb March....
2 2 0
I know I can do it by having query for each column, get only relevent rows for this specific month and just count them.
As follows:
Select (Select count(*)
from Shipments
Where EXTRACT(YEAR FROM dateshipped)::int=2016 and EXTRACT(MONTH FROM dateshipped)::int=1 )as JAN,
(Select count(*)
from Shipments
Where EXTRACT(YEAR FROM dateshipped)::int=2016 and EXTRACT(MONTH FROM dateshipped)::int=2 )as FEB
This works however its too much of the same code...
I am wondring if it is possible to do it with a single FROM statment and each column get it's own relevent rows for count.
Something like:
Select COL1,COL2,COL3...
from Shipments
Where EXTRACT(YEAR FROM dateshipped)::int=2016;
and have something like:
COL1 = count only JAN records
COL2 = count only FEB records
....
maybe there is something with Parations on months or any other solution?
You need a pivot query to accomplish this:
SELECT SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 1 THEN 1 ELSE 0 END) AS Jan,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 2 THEN 1 ELSE 0 END) AS Feb,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 3 THEN 1 ELSE 0 END) AS Mar,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 4 THEN 1 ELSE 0 END) AS Apr,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 5 THEN 1 ELSE 0 END) AS May,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 6 THEN 1 ELSE 0 END) AS Jun,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 7 THEN 1 ELSE 0 END) AS Jul,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 8 THEN 1 ELSE 0 END) AS Aug,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 9 THEN 1 ELSE 0 END) AS Sep,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 10 THEN 1 ELSE 0 END) AS Oct,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 11 THEN 1 ELSE 0 END) AS Nov,
SUM(CASE WHEN EXTRACT(MONTH FROM dateshipped)::int = 12 THEN 1 ELSE 0 END) AS Dec
FROM Shipments
WHERE EXTRACT(YEAR FROM dateshipped)::int=2016
Since 9.4 you can use FILTER
SELECT
count(*) AS total,
count(*) FILTER (WHERE Extract(MONTH FROM dateshipped)::int=1) AS JAN,
count(*) FILTER (WHERE Extract(MONTH FROM dateshipped)::int=2) AS FEB,
...
FROM Shipments
WHERE Extract(YEAR FROM dateshipped)::int=2016;
Try case with sum function:
Select
sum(case when extract(MONTH from dateshipped)=1 then 1 else 0 end) as jan,
sum(case when extract(MONTH from dateshipped)=2 then 1 else 0 end) as feb,
sum(case when extract(MONTH from dateshipped)=3 then 1 else 0 end) as march
.....
.....
from Shipments
Where EXTRACT(YEAR FROM dateshipped)::int=2016;

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.

Re-Ordering the Months By Federal Fiscal Year

When running the following query I am trying to find a way to display the returned months by federal fiscal year instead of normal sequential value.
(ie I want to display months in the following order Oct, Nov, Dec, Jan, Feb, Mar, Apr, May Jun, Jul, Aug, Sept instead of Jan thru Dec.) Thanks
select wrkgrp,
sum (case when extract(month from reportdate) = 1 then 1 else 0 end) as January,
sum (case when extract(month from reportdate) = 2 then 1 else 0 end) as February,
sum (case when extract(month from reportdate) = 3 then 1 else 0 end) as March,
sum (case when extract(month from reportdate) = 4 then 1 else 0 end) as April,
sum (case when extract(month from reportdate) = 5 then 1 else 0 end) as May,
sum (case when extract(month from reportdate) = 6 then 1 else 0 end) as June,
sum (case when extract(month from reportdate) = 7 then 1 else 0 end) as July,
sum (case when extract(month from reportdate) = 8 then 1 else 0 end) as August,
sum (case when extract(month from reportdate) = 9 then 1 else 0 end) as September,
sum (case when extract(month from reportdate) = 10 then 1 else 0 end) as October,
sum (case when extract(month from reportdate) = 11 then 1 else 0 end) as November,
sum (case when extract(month from reportdate) = 12 then 1 else 0 end) as December,
from workorder
where reportdate between to_date ('2014-10-01 00:00:00', 'yyyy/mm/dd hh24:mi:ss')
and to_date ('2015-09-30 00:00:00', 'yyyy/mm/dd hh24:mi:ss')
and wrkgrp = 'PublicWorks'
group by 'wrkgrp;'
The fields will display in your results (horizontally) in the order you list them in your select statement. Structure your statement with Oct listed first like this:
select wrkgrp,
sum (case when extract(month from reportdate) = 10 then 1 else 0 end) as October,
sum (case when extract(month from reportdate) = 11 then 1 else 0 end) as November,
sum (case when extract(month from reportdate) = 12 then 1 else 0 end) as December,
sum (case when extract(month from reportdate) = 1 then 1 else 0 end) as January,
sum (case when extract(month from reportdate) = 2 then 1 else 0 end) as February,
sum (case when extract(month from reportdate) = 3 then 1 else 0 end) as March,
sum (case when extract(month from reportdate) = 4 then 1 else 0 end) as April,
sum (case when extract(month from reportdate) = 5 then 1 else 0 end) as May,
sum (case when extract(month from reportdate) = 6 then 1 else 0 end) as June,
sum (case when extract(month from reportdate) = 7 then 1 else 0 end) as July,
sum (case when extract(month from reportdate) = 8 then 1 else 0 end) as August,
sum (case when extract(month from reportdate) = 9 then 1 else 0 end) as September
from workorder
where reportdate between to_date ('2014-10-01 00:00:00', 'yyyy/mm/dd hh24:mi:ss') ad to_date ('2015-09-30 00:00:00', 'yyyy/mm/dd hh24:mi:ss') and
wrkgrp = 'PublicWorks'
group by 'wrkgrp;'
Add case statements in your order by clause to get the desired sort.
ORDER BY
CASE WHEN extract(month from reportdate) = 10 THEN 1
CASE WHEN extract(month from reportdate) = 11 THEN 2
ASC