SQL-Server Unpivot/Pivot Example - sql

i'm making an application to manage hotel bookings and i need to show the ocupation rate per month in a year. I made a query that kinda solves the problem but i want presented in another format.
My current query return the following table (2x12):
January|February|March|April| ..... and so on
20 15 18 20 ..... and so on
And i want something like this (12x2):
January|20
February|15
March|18
... |...
This is my query:
Select
SUM(CASE WHEN datename(month, [CheckIn]) = 'January' or datename(month, [CheckOut]) = 'January' THEN 1 ELSE 0 END) January,
SUM(CASE WHEN datename(month, [CheckIn]) = 'February' or datename(month, [CheckOut]) = 'February' THEN 1 ELSE 0 END) February,
SUM(CASE WHEN datename(month, [CheckIn]) = 'March' or datename(month, [CheckOut]) = 'March' THEN 1 ELSE 0 END) March,
SUM(CASE WHEN datename(month, [CheckIn]) = 'April' or datename(month, [CheckOut]) = 'April' THEN 1 ELSE 0 END) April,
SUM(CASE WHEN datename(month, [CheckIn]) = 'May' or datename(month, [CheckOut]) = 'May' THEN 1 ELSE 0 END) May,
SUM(CASE WHEN datename(month, [CheckIn]) = 'June' or datename(month, [CheckOut]) = 'June' THEN 1 ELSE 0 END) June,
SUM(CASE WHEN datename(month, [CheckIn]) = 'July' or datename(month, [CheckOut]) = 'July' THEN 1 ELSE 0 END) July,
SUM(CASE WHEN datename(month, [CheckIn]) = 'August' or datename(month, [CheckOut]) = 'August' THEN 1 ELSE 0 END) August,
SUM(CASE WHEN datename(month, [CheckIn]) = 'September' or datename(month, [CheckOut]) = 'September' THEN 1 ELSE 0 END) September,
SUM(CASE WHEN datename(month, [CheckIn]) = 'October' or datename(month, [CheckOut]) = 'October' THEN 1 ELSE 0 END) October,
SUM(CASE WHEN datename(month, [CheckIn]) = 'November' or datename(month, [CheckOut]) = 'November' THEN 1 ELSE 0 END) November,
SUM(CASE WHEN datename(month, [CheckIn]) = 'December' or datename(month, [CheckOut]) = 'December' THEN 1 ELSE 0 END) December
FROM {Booking} INNER JOIN {Status} ON {Booking}.[StatusId] = {Status}.[Id]
WHERE {Booking}.[CheckIn] >= #BeginDate AND {Booking}.[CheckOut] <= #EndDate AND {Status}.[Label] <> 'Canceled'
Any help would be appreciated, i'm stuck and theres is not that much info on the web, thanks!

Looks like you're trying to do an UNPIVOT:
SELECT Month, CheckIns
FROM
(Select
SUM(CASE WHEN datename(month, [CheckIn]) = 'January' or datename(month, [CheckOut]) = 'January' THEN 1 ELSE 0 END) January,
SUM(CASE WHEN datename(month, [CheckIn]) = 'February' or datename(month, [CheckOut]) = 'February' THEN 1 ELSE 0 END) February,
SUM(CASE WHEN datename(month, [CheckIn]) = 'March' or datename(month, [CheckOut]) = 'March' THEN 1 ELSE 0 END) March,
SUM(CASE WHEN datename(month, [CheckIn]) = 'April' or datename(month, [CheckOut]) = 'April' THEN 1 ELSE 0 END) April,
SUM(CASE WHEN datename(month, [CheckIn]) = 'May' or datename(month, [CheckOut]) = 'May' THEN 1 ELSE 0 END) May,
SUM(CASE WHEN datename(month, [CheckIn]) = 'June' or datename(month, [CheckOut]) = 'June' THEN 1 ELSE 0 END) June,
SUM(CASE WHEN datename(month, [CheckIn]) = 'July' or datename(month, [CheckOut]) = 'July' THEN 1 ELSE 0 END) July,
SUM(CASE WHEN datename(month, [CheckIn]) = 'August' or datename(month, [CheckOut]) = 'August' THEN 1 ELSE 0 END) August,
SUM(CASE WHEN datename(month, [CheckIn]) = 'September' or datename(month, [CheckOut]) = 'September' THEN 1 ELSE 0 END) September,
SUM(CASE WHEN datename(month, [CheckIn]) = 'October' or datename(month, [CheckOut]) = 'October' THEN 1 ELSE 0 END) October,
SUM(CASE WHEN datename(month, [CheckIn]) = 'November' or datename(month, [CheckOut]) = 'November' THEN 1 ELSE 0 END) November,
SUM(CASE WHEN datename(month, [CheckIn]) = 'December' or datename(month, [CheckOut]) = 'December' THEN 1 ELSE 0 END) December
FROM {Booking} INNER JOIN {Status} ON {Booking}.[StatusId] = {Status}.[Id]
WHERE {Booking}.[CheckIn] >= #BeginDate AND {Booking}.[CheckOut] <= #EndDate AND {Status}.[Label] <> 'Canceled'
) monthTotals
UNPIVOT
(CheckIns FOR Month IN
(January, February, March, April, May, June, July, August, September, October, November, December)
) AS upvt
Here's a simplified SQLFiddle of this
And here's a doc page on PIVOT and UNPIVOT

You can make your case statements a little shorter/simpler so it's easier to read. MONTH() is a easier to read function and getting rid of else will mean if it simply return a null which SUM() treats like a 0
SELECT [Month], CheckIns
FROM
(
Select
SUM(CASE WHEN MONTH([CheckIn]) = 01 or MONTH([CheckOut]) = 01 THEN 1 END) January,
SUM(CASE WHEN MONTH([CheckIn]) = 02 or MONTH([CheckOut]) = 02 THEN 1 END) February,
SUM(CASE WHEN MONTH([CheckIn]) = 03 or MONTH([CheckOut]) = 03 THEN 1 END) March,
SUM(CASE WHEN MONTH([CheckIn]) = 04 or MONTH([CheckOut]) = 04 THEN 1 END) April,
SUM(CASE WHEN MONTH([CheckIn]) = 05 or MONTH([CheckOut]) = 05 THEN 1 END) May,
SUM(CASE WHEN MONTH([CheckIn]) = 06 or MONTH([CheckOut]) = 06 THEN 1 END) June,
SUM(CASE WHEN MONTH([CheckIn]) = 07 or MONTH([CheckOut]) = 07 THEN 1 END) July,
SUM(CASE WHEN MONTH([CheckIn]) = 08 or MONTH([CheckOut]) = 08 THEN 1 END) August,
SUM(CASE WHEN MONTH([CheckIn]) = 09 or MONTH([CheckOut]) = 09 THEN 1 END) September,
SUM(CASE WHEN MONTH([CheckIn]) = 10 or MONTH([CheckOut]) = 10 THEN 1 END) October,
SUM(CASE WHEN MONTH([CheckIn]) = 11 or MONTH([CheckOut]) = 11 THEN 1 END) November,
SUM(CASE WHEN MONTH([CheckIn]) = 12 or MONTH([CheckOut]) = 12 THEN 1 END) December
FROM [Booking]
INNER JOIN {Status} ON {Booking}.[StatusId] = {Status}.[Id]
WHERE {Booking}.[CheckIn] >= #BeginDate AND {Booking}.[CheckOut] <= #EndDate AND {Status}.[Label] <> 'Canceled'
) MONTHTotals
UNPIVOT
(
CheckIns FOR [Month] IN
(January, February, March, April, May, June, July, August, September, October, November, December)
) AS upvt

Related

SQL get total number and using pivot at the same time

I got two tables with the relationship like this
I have a data set like this
and want to get ALL the demerits, the code, description, total number of offences committed for the demerit code so far in any month (of any year) and then the total of offences committed for the demerit
code in each month (of any year) which is basically a result like this
I can get the total number(by using group by) and monthly data(by using pivot rows as columns) separately, but don't know how to get them in one query. Any help would be appreciated.
select * from (
select
d.dem_code,
d.dem_code as dem_code_copy,
d.dem_description,
case
when EXTRACT(month FROM off_datetime) = 1 then 'Jan'
when EXTRACT(month FROM off_datetime) = 2 then 'Feb'
when EXTRACT(month FROM off_datetime) = 3 then 'Mar'
when EXTRACT(month FROM off_datetime) = 4 then 'Apr'
when EXTRACT(month FROM off_datetime) = 5 then 'May'
when EXTRACT(month FROM off_datetime) = 6 then 'Jun'
when EXTRACT(month FROM off_datetime) = 7 then 'Jul'
when EXTRACT(month FROM off_datetime) = 8 then 'Aug'
when EXTRACT(month FROM off_datetime) = 9 then 'Sep'
when EXTRACT(month FROM off_datetime) = 10 then 'Oct'
when EXTRACT(month FROM off_datetime) = 11 then 'Nov'
when EXTRACT(month FROM off_datetime) = 12 then 'Dec'
end
as "Month"
from demerit d
left join offence o on d.dem_code = o.dem_code
order by d.dem_code
)
pivot(
count(dem_code_copy)
for "Month"
in (
'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'
)
)
This query gives me the monthly result
select
d.dem_code,
d.dem_description,
count(o.off_no) as total
from demerit d
left join offence o on d.dem_code = o.dem_code
group by d.dem_code, d.dem_description
order by d.dem_code
This query gives the total number
I would just use conditional aggregation:
select d.dem_code, d.dem_description,
sum(case when EXTRACT(month FROM off_datetime) = 1 then 1 else 0 end) as Jan,
sum(case when EXTRACT(month FROM off_datetime) = 2 then 1 else 0 end) as Feb
sum(case when EXTRACT(month FROM off_datetime) = 3 then 1 else 0 end) as Mar,
sum(case when EXTRACT(month FROM off_datetime) = 4 then 1 else 0 end) as Apr,
sum(case when EXTRACT(month FROM off_datetime) = 5 then 1 else 0 end) as May,
sum(case when EXTRACT(month FROM off_datetime) = 6 then 1 else 0 end) as Jun,
sum(case when EXTRACT(month FROM off_datetime) = 7 then 1 else 0 end) as Jul,
sum(case when EXTRACT(month FROM off_datetime) = 8 then 1 else 0 end) as Aug,
sum(case when EXTRACT(month FROM off_datetime) = 9 then 1 else 0 end) as Sep,
sum(case when EXTRACT(month FROM off_datetime) = 10 then 1 else 0 end) as Oct,
sum(case when EXTRACT(month FROM off_datetime) = 11 then 1 else 0 end) as Nov,
sum(case when EXTRACT(month FROM off_datetime) = 12 then 1 else 0 end) as Dec
from demerit d left join
offence o
on d.dem_code = o.dem_code
group by d.dem_code, d.dem_description;

SQL Query for count by month over multiple years

I've been using the query below to get me a count of records by month. Works good for a specific year.
However, its a bit of a pain if I want to compare a count from Jan 2018 to Jan 2019. Especially if I want to graph it.
How might I adjust this so that I could get a Jan 18, Feb 18,....Jan 19 type of result by giving a span of years.
This is Postgres 9.6
Thanks!
SELECT
count(case when to_char(t.order_date, 'MM') = '01' then 1 END) as Jan,
count(case when to_char(t.order_date, 'MM') = '02' then 1 END) as Feb,
count(case when to_char(t.order_date, 'MM') = '03' then 1 END) as Mar,
count(case when to_char(t.order_date, 'MM') = '04' then 1 END) as Apr,
count(case when to_char(t.order_date, 'MM') = '05' then 1 END) as May,
count(case when to_char(t.order_date, 'MM') = '06' then 1 END) as June,
count(case when to_char(t.order_date, 'MM') = '07' then 1 END) as Jul,
count(case when to_char(t.order_date, 'MM') = '08' then 1 END) as Aug,
count(case when to_char(t.order_date, 'MM') = '09' then 1 END) as Sep,
count(case when to_char(t.order_date, 'MM') = '10' then 1 END) as Oct,
count(case when to_char(t.order_date, 'MM') = '11' then 1 END) as Nov,
count(case when to_char(t.order_date, 'MM') = '12' then 1 END) as Dec
FROM transactions as t
WHERE to_char(t.order_date, 'YYYY') = '2019'
You can make “buckets” of your data by timestamp, by combining:
Truncate a timestamp value to a specified precision, flattening those values to a single value.
Group by the resulting lower-precision values.
SELECT
date_trunc('month', t.order_date) AS order_month,
count(t.order_id) AS count
FROM transaction AS t
GROUP BY order_month
ORDER BY order_month
Then it's up to you what years to limit the result to:
SELECT
date_trunc('month', t.order_date) AS order_month,
count(t.order_id) AS count
FROM transaction AS t
WHERE
date_part('year', t.order_date) = 2019
GROUP BY order_month
ORDER BY order_month
Please check below query, is this relevant?
Blockquote
SELECT
to_char(order_date, 'YYYY'),
count(case when to_char(t.order_date, 'MM') = '01' then 1 END) as Jan,
count(case when to_char(t.order_date, 'MM') = '02' then 1 END) as Feb,
count(case when to_char(t.order_date, 'MM') = '03' then 1 END) as Mar,
count(case when to_char(t.order_date, 'MM') = '04' then 1 END) as Apr,
count(case when to_char(t.order_date, 'MM') = '05' then 1 END) as May,
count(case when to_char(t.order_date, 'MM') = '06' then 1 END) as June,
count(case when to_char(t.order_date, 'MM') = '07' then 1 END) as Jul,
count(case when to_char(t.order_date, 'MM') = '08' then 1 END) as Aug,
count(case when to_char(t.order_date, 'MM') = '09' then 1 END) as Sep,
count(case when to_char(t.order_date, 'MM') = '10' then 1 END) as Oct,
count(case when to_char(t.order_date, 'MM') = '11' then 1 END) as Nov,
count(case when to_char(t.order_date, 'MM') = '12' then 1 END) as Dec
FROM transactions as t where to_char(order_date, 'YYYY') in ('2018','2019')
group by to_char(order_date, 'YYYY');
Blockquote
Do you want the results on different rows?
SELECT to_char(t.order_date, 'YYYY') = '2019',
count(*) filter (to_char(t.order_date, 'MM') = '01') as Jan,
count(*) filter (to_char(t.order_date, 'MM') = '02') as Feb,
. . .
count(*) filter (to_char(t.order_date, 'MM') = '12') as Dec
FROM transactions as t
GROUP BY to_char(t.order_date, 'YYYY') = '2019'

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

How to change column position based on condition in a select query where having with clasue

in the below query i have succeeded to get my data in a table starting from Jan, but i want to get starting month based on given date.
ex: if month(inputdate) is 11 then table columns should start from nov and end with sep
I have tried with if else and dynamic query and not succeeded because of with clause
Any help would be appreciated!
WITH taskspecdata AS (select left(datename(month,max(approvalinfo_enddate)),3)as approvedMonth,
year(max(approvalinfo_enddate)) as approvedYear, month(max(approvalInfo_endDate)) as sortMonth,
Document_Id as docid,DocVersion_Counter as versions,docversion_Id as verid
from [webcenter].[WcReports_DocApprovalQ] where
(ApprovalInfo_EndDate)>= DATEADD(year,-1,GETDATE()) and (ApprovalInfo_EndDate)<= GETDATE()
group by [WcReports_DocApprovalQ].DocVersion_Id,Document_Id,DocVersion_Counter)
select versions,
sum(case when approvedMonth = 'Jan' then 1 else 0 end) Jan,
sum(case when approvedMonth = 'Feb' then 1 else 0 end) Feb,
sum(case when approvedMonth = 'Mar' then 1 else 0 end) Mar,
sum(case when approvedMonth = 'Apr' then 1 else 0 end) Apr,
sum(case when approvedMonth = 'May' then 1 else 0 end) May,
sum(case when approvedMonth = 'Jun' then 1 else 0 end) Jun,
sum(case when approvedMonth = 'Jul' then 1 else 0 end) Jul,
sum(case when approvedMonth = 'Aug' then 1 else 0 end) Aug,
sum(case when approvedMonth = 'Sep' then 1 else 0 end) Sep,
sum(case when approvedMonth = 'Oct' then 1 else 0 end) Oct,
sum(case when approvedMonth = 'Nov' then 1 else 0 end) Nov,
sum(case when approvedMonth = 'Dec' then 1 else 0 end) Dec from taskspecdata group by versions
Result columns:
versions Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
but i want to start from input month`enter code here`
if given month is nov then
versions Nov Dec Jan Feb Mar Apr May Jun Jul Aug Sep Oct
select id,Month where id>input data union
select id,Month where id<input data

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