Without PIVOT, display data where GROUP BY column are the column names - sql

I have data that looks like the following:
Name Date Hr Min Amt
Joe 20150320 08 00 5
Joe 20150320 08 15 3
Carl 20150320 09 30 1
Carl 20150320 09 45 2
Ray 20150320 13 00 8
Ray 20150320 13 30 6
A simple GROUP BY [Name], [Date], [Hr] would display the total by hour for each salesman.
Without using PIVOT or dynamic sql, how can I display this data where the hours are the columns? With PIVOT I would need to detail each hour, so if the data above were the only data, there would be 3 columns with data (8, 9, 13), and 21 empty columns.
The reason I want to do this is because I would like to create an SSRS report where the columns are the hours. Unfortunately, I can't use a matrix because I can't sort by the column detail (ie. click on "8" and display from smallest to largest); I've already confirmed this limitation with an MS expert.
So any help is appreciated. We have Sql Server 2008 R2.
Thanks.

Select Name
,[Date]
,SUM(Case When Hr = '00' THEN Amt END) [00]
,SUM(Case When Hr = '01' THEN Amt END) [01]
,SUM(Case When Hr = '02' THEN Amt END) [02]
,SUM(Case When Hr = '03' THEN Amt END) [03]
,SUM(Case When Hr = '04' THEN Amt END) [04]
,SUM(Case When Hr = '05' THEN Amt END) [05]
,SUM(Case When Hr = '06' THEN Amt END) [06]
,SUM(Case When Hr = '07' THEN Amt END) [07]
,SUM(Case When Hr = '08' THEN Amt END) [08]
,SUM(Case When Hr = '09' THEN Amt END) [09]
,SUM(Case When Hr = '10' THEN Amt END) [10]
,SUM(Case When Hr = '11' THEN Amt END) [11]
,SUM(Case When Hr = '12' THEN Amt END) [12]
,SUM(Case When Hr = '13' THEN Amt END) [13]
,SUM(Case When Hr = '14' THEN Amt END) [14]
,SUM(Case When Hr = '15' THEN Amt END) [15]
,SUM(Case When Hr = '16' THEN Amt END) [16]
,SUM(Case When Hr = '17' THEN Amt END) [17]
,SUM(Case When Hr = '18' THEN Amt END) [18]
,SUM(Case When Hr = '19' THEN Amt END) [19]
,SUM(Case When Hr = '20' THEN Amt END) [20]
,SUM(Case When Hr = '21' THEN Amt END) [21]
,SUM(Case When Hr = '22' THEN Amt END) [22]
,SUM(Case When Hr = '23' THEN Amt END) [23]
From TablenName
Group By Name ,[Date]

something like this work?? put your key fields into temp tables dont join them so you create a possibility for everything then sub query your amt in.
select * into #Temp1 from (
select '01' as 'Pivot_Hour'
union all
select '02' as 'Pivot_Hour'
union all
select '03' as 'Pivot_Hour'
union all
select '04' as 'Pivot_Hour'
union all
select '05' as 'Pivot_Hour'
--Put all 24 hours in....
)
x
select * into #Temp2 from (
select 'Carl' as 'User'
union all
select 'Joe' as 'User'
union all
select 'Ray' as 'User'
union all
select 'Dave' as 'User'
union all
select 'Seve' as 'User'
---Could select distinct from your data...
)
x
Select * into #Temp3 from (
select '20150321' as 'Date'
union all
select '20150322' as 'Date'
union all
select '20150323' as 'Date'
union all
select '20150324' as 'Date'
union all
select '20150325' as 'Date'
---Could select distinct from your data...
)
x
select *
,(select sum(yrd.amt) from Yourdata Yrd
where yrd.Name = t2.User
and yrd.date = t3.date
and yrd.Hr = t1.Pivot_Hour)Amt
from #Temp1 t1,#Temp2 t2,#Temp3 t3
drop table #Temp1
drop table #Temp2
drop table #Temp3

Related

How pivot month name in SQL Server after a date

I have a table in SQL Server with these columns:
id int pk
date datetime
value numeric
This is my select query
SELECT
O.Date AS DATE,
O.Value AS VALUE
FROM
Orders O
WHERE
YEAR(Date) = #Year
and this is my data
I want this output:
JAN FEB MAR APR MAY JUNE JULY AUG SEPT OCT NOV DEC
-----------------------------------------------------------------------
600 1200 600 600 0 0 0 0 0 0 0 0
Doesn't need a subquery. Something like this should work
select sum(case when dt.mo=1 then o.[Value] else 0 end) 'Jan',
sum(case when dt.mo=2 then o.[Value] else 0 end) 'Feb',
sum(case when dt.mo=3 then o.[Value] else 0 end) 'Mar',
sum(case when dt.mo=4 then o.[Value] else 0 end) 'Apr',
sum(case when dt.mo=5 then o.[Value] else 0 end) 'May',
sum(case when dt.mo=6 then o.[Value] else 0 end) 'Jun',
sum(case when dt.mo=7 then o.[Value] else 0 end) 'Jul',
sum(case when dt.mo=8 then o.[Value] else 0 end) 'Aug',
sum(case when dt.mo=9 then o.[Value] else 0 end) 'Sep',
sum(case when dt.mo=10 then o.[Value] else 0 end) 'Oct',
sum(case when dt.mo=11 then o.[Value] else 0 end) 'Nov',
sum(case when dt.mo=12 then o.[Value] else 0 end) 'Dec'
from Orders o
cross apply (select month(o.[Date]) mo) dt
where year(o.[DAte])=#Year;
You may try this-
Select
max(case when [Month] = 'Jan' then Value end) As "JAN"
,max(case when [Month] = 'Feb' then Value end) As "FEB"
,.....
,max(case when [Month] = 'Dec' then Value end) As "DEC"
from
(SELECT
Format(O.Date, 'MMM') as [Month],
Max(O.Value) AS VALUE
FROM Orders O
WHERE YEAR(Date) = #Year
Group by
Format(O.Date, 'MMM'))T;

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

Pivot and get count of rows in each cell?

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

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.