Transposing columns sql server - sql-server

I have a slightly complex query below:
with t as (
select a.ID, a.Date_Reported AS [Date Sent], b.Date_Received AS [Date Returned],
(datediff(dd, a.date_reported, b.date_received)
+ CASE WHEN Datepart(dw, b.date_received) = 7 THEN 1 ELSE 0 END
- (Datediff(wk, a.date_reported, b.date_received) * 2 )
- CASE WHEN Datepart(dw, b.date_received) = 1 THEN 1 ELSE 0 END +
- CASE WHEN Datepart(dw, b.date_received) = 1 THEN 1 ELSE 0
END) AS [Time_Spent]
from TX_ext a
join TX b on b.id on a.id
)
select
sum(case when Time_Spent between 0 and 3 then 1 else 0 end) as _0_3_days,
sum(case when Time_Spent = 4 then 1 else 0 end) as _4_days,
sum(case when Time_Spent = 5 then 1 else 0 end) as _5_days,
sum(case when Time_Spent between 6 and 8 then 1 else 0 end) as _6_8_days,
sum(case when Time_Spent >= 9 then 1 else 0 end) as more_than_9_days,
avg(case when Time_Spent between 0 and 3 then 100.0 else 0 end) as _0_3_percent,
avg(case when Time_Spent = 4 then 100.0 else 0 end) as _4_percent,
avg(case when Time_Spent = 5 then 100.0 else 0 end) as _5_percent,
avg(case when Time_Spent between 6 and 8 then 100.0 else 0 end) as _6_8_percent,
avg(case when Time_Spent >= 9 then 100.0 else 0 end) as more_than_9_day_percent
from t
The above query gives me the below table:
0-3 | 4 | 5 | 6-8 | 9+ | 0-3% | 4% | 5% | 6-8% | 9+%
2 | 3 | 1 | 3 | 1 | 20 | 30 | 10 | 30 | 10
However what I would ideally like is this (the % figures transposed as a row) and also headings as the FIRST column:
Time Taken (days) | 0-3 | 4 | 5 | 6-8 | 9+
Count | 2 | 3 | 1 | 3 | 1
% | 20 | 30| 10| 30 | 10
Any ideas? Thanks in advance

you can do this using CROSS APPLY like below query
See live demo
; with t as
(
select
a.ID,
a.Date_Reported AS [Date Sent],
b.Date_Received AS [Date Returned],
(datediff(dd, a.date_reported, b.date_received)
+ CASE WHEN Datepart(dw, b.date_received) = 7 THEN 1 ELSE 0 END
- (Datediff(wk, a.date_reported, b.date_received) * 2 )
- CASE WHEN Datepart(dw, b.date_received) = 1 THEN 1 ELSE 0 END +
- CASE WHEN Datepart(dw, b.date_received) = 1 THEN 1 ELSE 0
END) AS [Time_Spent]
from TX_ext a
join TX b on b.id on a.id
)
select V.*
from
(
select
sum(case when Time_Spent between 0 and 3 then 1 else 0 end) as _0_3_days,
sum(case when Time_Spent = 4 then 1 else 0 end) as _4_days,
sum(case when Time_Spent = 5 then 1 else 0 end) as _5_days,
sum(case when Time_Spent between 6 and 8 then 1 else 0 end) as _6_8_days,
sum(case when Time_Spent >= 9 then 1 else 0 end) as more_than_9_days,
avg(case when Time_Spent between 0 and 3 then 100.0 else 0 end) as _0_3_percent,
avg(case when Time_Spent = 4 then 100.0 else 0 end) as _4_percent,
avg(case when Time_Spent = 5 then 100.0 else 0 end) as _5_percent,
avg(case when Time_Spent between 6 and 8 then 100.0 else 0 end) as _6_8_percent,
avg(case when Time_Spent >= 9 then 100.0 else 0 end) as more_than_9_day_percent
from t
) T1
cross apply
( values
('Count',[_0_3_days] , [_4_days] , [_5_days] , [_6_8_days] , [more_than_9_days]),
('%',[_0_3_percent] , [_4_percent] , [_5_percent] , [_6_8_percent] , [more_than_9_day_percent] )
)
v([Time Taken (days)],[0-3],[4],[5],[6-8],[9+])

select
sum(case when Time_Spent between 0 and 3 then 1 else 0 end) as _0_3,
sum(case when Time_Spent = 4 then 1 else 0 end) as _4,
sum(case when Time_Spent = 5 then 1 else 0 end) as _5,
sum(case when Time_Spent between 6 and 8 then 1 else 0 end) as _6_8,
sum(case when Time_Spent >= 9 then 1 else 0 end) as more_than_9
from t
union
select
avg(case when Time_Spent between 0 and 3 then 100.0 else 0 end) as _0_3,
avg(case when Time_Spent = 4 then 100.0 else 0 end) as _4,
avg(case when Time_Spent = 5 then 100.0 else 0 end) as _5,
avg(case when Time_Spent between 6 and 8 then 100.0 else 0 end) as _6_8,
avg(case when Time_Spent >= 9 then 100.0 else 0 end) as more_than_9
from t

Related

IBM DB2 PIVOT A TABLE FULL OF DATES

I have this table in DB2:
DATE
----------
09/11/2021
06/10/2021
28/11/2021
17/11/2021
11/10/2021
24/11/2021
07/11/2021
30/11/2021
I want to count how many times a date appeared in the table and group it by year and month, and display it like this:
| YEAR | OCTOBER | NOVEMBER |
----------------------------
| 2021 | 2 | 6 |
As months are a known quantity you could use a sum of a case statement:
select year(datecol) as year
,sum(case when month(datecol) = 1 then 1 else 0 end) as jan
,sum(case when month(datecol) = 2 then 1 else 0 end) as feb
,sum(case when month(datecol) = 3 then 1 else 0 end) as mar
,sum(case when month(datecol) = 4 then 1 else 0 end) as apr
,sum(case when month(datecol) = 5 then 1 else 0 end) as may
,sum(case when month(datecol) = 6 then 1 else 0 end) as jun
,sum(case when month(datecol) = 7 then 1 else 0 end) as jul
,sum(case when month(datecol) = 8 then 1 else 0 end) as aug
,sum(case when month(datecol) = 9 then 1 else 0 end) as sep
,sum(case when month(datecol) = 10 then 1 else 0 end) as oct
,sum(case when month(datecol) = 11 then 1 else 0 end) as nov
,sum(case when month(datecol) = 12 then 1 else 0 end) as dec
from datetest
group by year(datecol)
order by 1;
That will give you output similar to this:
YEAR JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC
----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
2018 0 0 0 0 0 0 0 0 0 0 3 0
2019 0 0 0 0 0 0 0 0 0 1 2 0
2020 0 0 0 0 0 0 0 0 0 1 1 0
2021 0 0 0 0 0 0 0 0 0 2 6 0
You may use a generic routine described at the link dynamic pivot SQL Query in Db2.
Use the following call to get the desired result set for your case:
CALL PIVOT
(
'SELECT YEAR (DATE) AS YEAR, TO_CHAR (DATE, ''MONTH'') AS MONTH FROM DATES'
, 'YEAR'
, 'MONTH'
, 'MONTH'
, 'count'
, 'SESSION.PIVOT'
, '-'
, ?, ?, ?
);
The result is:
YEAR
NOVEMBER
OCTOBER
2021
6
2

Insert Query in SQL Server

I have this table TAB
ID | Trans
------------
1 | 99
2 | 99
3 | 99
2 | 90
4 | 22
4 | 22
2 | 99
2 | 90
I want to get the count of trans that appear together for a single id, for eg, '1 has 90 & 99' and '2 has 90 & 99' in the entire table so the count is 2. This is similar to Apriori Algorithm's Third Step.
I tried this but didn't work-
select
count(trans)
from
Tab
where
trans = 99 & 90
group by
ID
having
ID = 2
My expected ans for Trans- 90 & 99 is
Trans1 | Trans2 | Support
------------
90 | 99 | 1
I also want to insert this into a new table.
If I understood your problem correctly, you can use SUM(CASE WHEN...END) for this:
DECLARE
#trans1 INT = 99,
#trans2 INT = 90
SELECT
ID,
PairCount =
CASE
WHEN SUM(CASE WHEN Trans = #trans1 THEN 1 ELSE 0 END) >= SUM(CASE WHEN Trans = #trans2 THEN 1 ELSE 0 END)
THEN SUM(CASE WHEN Trans = #trans2 THEN 1 ELSE 0 END)
ELSE SUM(CASE WHEN Trans = #trans1 THEN 1 ELSE 0 END)
END,
Trans1 = SUM(CASE WHEN Trans = #trans1 THEN 1 ELSE 0 END),
Trans2 = SUM(CASE WHEN Trans = #trans2 THEN 1 ELSE 0 END)
FROM DS
WHERE Trans IN (#trans1, #trans2)
GROUP BY ID
RESULT
ID PairCount Trans1 Trans2
----------- ----------- ----------- -----------
1 0 1 0
2 2 2 2
3 0 1 0

SQL SERVER How to combine two query on the same table that has "group by"

I want to combine two queries on the same table that has group by.
here is my table :
Date##### | Value1 | Value2 | Value3 | Type
23/04/2014 | 1,2 | 12,3 | 10 | Green
23/04/2014 | 11,2 | 3 | 10,3 | Non-Green
24/04/2014 | 10,9 | 3 | 11 | Green
24/04/2014 | 2,3 | 12,3 | 8 | Green
25/04/2014 | 10 | 2 | 10,8 | Non-Green
25/04/2014 | 1,4 | 5 | 12 | Green
I want it to display:
Date##### | Count |Type
23/04/2014 | 2 | Green
23/04/2014 | 2 | Non-Green
24/04/2014 | 3 | Green
25/04/2014 | 2 | Non-Green
25/04/2014 | 1 | Green
here is my first query :
Dim strCommand As String = "SELECT d, LW, cnt FROM(SELECT TOP 7 [date] AS d, [Type] as LW, SUM(CASE WHEN ManualAssists1 >= 10 THEN 1 ELSE 0 END + CASE WHEN ManualAssists2 >= 10 THEN 1 ELSE 0 END + CASE WHEN ManualAssists3 >= 10 THEN 1 ELSE 0 END) AS cnt FROM tbBooth where Type = 'Green' GROUP BY [date],[Type] ORDER BY [date] DESC) x ORDER BY d ASC"
It display :
Date##### | Count |Type
23/04/2014 | 2 | Green
24/04/2014 | 3 | Green
25/04/2014 | 1 | Green
my second query :
Dim strCommand As String = "SELECT d, LW, cnt FROM(SELECT TOP 7 [date] AS d, [Type] as LW, SUM(CASE WHEN ManualAssists1 >= 10 THEN 1 ELSE 0 END + CASE WHEN ManualAssists2 >= 10 THEN 1 ELSE 0 END + CASE WHEN ManualAssists3 >= 10 THEN 1 ELSE 0 END) AS cnt FROM tbBooth where Type = 'Non-Green' GROUP BY [date],[Type] ORDER BY [date] DESC) x ORDER BY d ASC"
It display :
Date##### | Count |Type
23/04/2014 | 2 | Non-Green
25/04/2014 | 2 | Non-Green
I want to combine both query to become one, and take the date, result of green and result of non-green. Assume that I have a lot of group of date, I want it to display only the last 7 group of date based on ASC order. I try to add UNION between my two query. Here is my code so far:
Dim strCommand As String = "Select 'Test1', * from tbBooth where type ='Green' and exist(SELECT d, LW, cnt FROM(SELECT TOP 7 [date] AS d, [Type] as LW, SUM(CASE WHEN Value1 >= 10 THEN 1 ELSE 0 END + CASE WHEN Value2 >= 10 THEN 1 ELSE 0 END + CASE WHEN Value3 >= 10 THEN 1 ELSE 0 END) AS cnt FROM tbBooth GROUP BY [date],[Type] ORDER BY [date] DESC) x ORDER BY d ASC) Union Select 'Test2', * from tbBooth where type ='Non-Green' and exist(SELECT d, LW, cnt FROM(SELECT TOP 7 [date] AS d, [Type] as LW, SUM(CASE WHEN Value1 >= 10 THEN 1 ELSE 0 END + CASE WHEN Value2 >= 10 THEN 1 ELSE 0 END + CASE WHEN Value3 >= 10 THEN 1 ELSE 0 END) AS cnt FROM tbBooth GROUP BY [date],[Type] ORDER BY [date] DESC) x ORDER BY d ASC)
it give me an error Incorrect syntax near the keyword 'SELECT'.
is ther anyway how to do it? I tried to look on other SO post but I don't have any clue to do it because both my query are complex...
Thanks in advances....
It's not that your combined query is complex, it's just that it's wrong.
What I don't understand is why you have the WHERE Type = 'Green' and 'Non-green'.
Given what you want as result, you could just remove that where and get pretty much what you're after:
SELECT d ,
LW ,
cnt
FROM ( SELECT TOP 7
[date] AS d ,
[Type] AS LW ,
SUM(CASE WHEN ManualAssists1 >= 10 THEN 1
ELSE 0
END + CASE WHEN ManualAssists2 >= 10 THEN 1
ELSE 0
END + CASE WHEN ManualAssists3 >= 10 THEN 1
ELSE 0
END) AS cnt
FROM tbBooth
--WHERE Type = 'Green'
GROUP BY [date] ,
[Type]
ORDER BY [date] DESC
) x
ORDER BY d ASC
Which gives:
2014-04-23 Green 2
2014-04-23 Non-Green 2
2014-04-24 Green 3
2014-04-25 Green 1
2014-04-25 Non-Green 2
I see no need to "combine" the two queries when the two queries are identical besides the 'Type' in the WHERE?
Bro, in your code change exist to exists
:) this should Work
Updated:
Add Top 7 to select
Select 'Test1', * from tbBooth
where type ='Green' and exists(SELECT **top 7** d, LW, cnt FROM(SELECT TOP 7 [date] AS d,
[Type] as LW,
SUM(CASE WHEN Value1 >= 10 THEN 1 ELSE 0 END
+ CASE WHEN Value2 >= 10 THEN 1 ELSE 0 END
+ CASE WHEN Value3 >= 10 THEN 1 ELSE 0 END) AS cnt
FROM tbBooth GROUP BY [date],[Type]
ORDER BY [date] DESC) x ORDER BY d ASC)
Union
Select 'Test2', * from tbBooth where type ='Non-Green'
and exists(SELECT **top 7** d, LW, cnt FROM(SELECT TOP 7
[date] AS d, [Type] as LW, SUM(CASE WHEN Value1 >= 10 THEN 1 ELSE 0 END
+ CASE WHEN Value2 >= 10 THEN 1 ELSE 0 END
+ CASE WHEN Value3 >= 10 THEN 1 ELSE 0 END) AS cnt
FROM tbBooth GROUP BY [date],[Type] ORDER BY [date] DESC) x ORDER BY d ASC)

Multiple PIVOTS? Need to count by Hour Per Month

This should be pretty simple. I have other PIVOT SQL queries working fine. I want to count logins: by hour, by month. I am thinking two PIVOTs or UNPIVOT and then PIVOT? Yes, I have dug around here, other sites, Google, etc. I am pretty stuck.
SELECT
loginid
,DATEPART(MONTH,logtime) Month
, DATEPART(HOUR, logtime) Hour
FROM somelog (nolock)
) temp
PIVOT (
COUNT(loginid)
FOR Month in (JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC)
) AS Pvt
What I want the results to be..
HOUR,JAN,FEB,MAR
00
01
02
..
23
and I don't need 8760 (365 x 24) of them
I have tried GROUP BY HOUR
I have tried GROUP BY temp.hour
I have also tried this as well.. It does seem to work, but I get Hour 00 for example 365 times.. Again, the GROUP BY issue..
SELECT
TimeOfDay
, [1] JAN
, [2] FEB
, [3] MAR
, [4] APR
, [5] MAY
, [6] JUN
, [7] JUL
, [8] AUG
, [9] SEP
, [10] OCT
, [11] NOV
, [12] DEC
FROM (SELECT logintime
, loginid
, datepart(month, logintime) [month]
, DatePart(hour, logintime) TimeOfDay
FROM sometable (nolock)) x
PIVOT (
COUNT(loginid)
for [month] in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])
) AS pvt
ORDER BY 1, 2
Thanks,
Kent
One way to do it
WITH hour_list AS (
SELECT 0 hour
UNION ALL
SELECT hour + 1 FROM hour_list WHERE hour < 23
)
SELECT h.hour,
COALESCE(jan, 0) jan,
COALESCE(feb, 0) feb,
COALESCE(mar, 0) mar,
COALESCE(apr, 0) apr,
COALESCE(may, 0) may,
COALESCE(jun, 0) jun,
COALESCE(jul, 0) jul,
COALESCE(aug, 0) aug,
COALESCE(sep, 0) sep,
COALESCE(oct, 0) oct,
COALESCE(nov, 0) nov,
COALESCE(dec, 0) dec
FROM hour_list h LEFT JOIN
(
SELECT DATEPART(HOUR, logtime) hour,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 1 THEN 1 END) jan,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 2 THEN 1 END) feb,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 3 THEN 1 END) mar,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 4 THEN 1 END) apr,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 5 THEN 1 END) may,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 6 THEN 1 END) jun,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 7 THEN 1 END) jul,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 8 THEN 1 END) aug,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 9 THEN 1 END) sep,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 10 THEN 1 END) oct,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 11 THEN 1 END) nov,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 12 THEN 1 END) dec
FROM somelog (NOLOCK)
GROUP BY DATEPART(HOUR, logtime)
) l
ON h.hour = l.hour
or with PIVOT
WITH hour_list AS (
SELECT 0 hour
UNION ALL
SELECT hour + 1 FROM hour_list WHERE hour < 23
)
SELECT h.hour,
COALESCE([1], 0) jan,
COALESCE([2], 0) feb,
COALESCE([3], 0) mar,
COALESCE([4], 0) apr,
COALESCE([5], 0) may,
COALESCE([6], 0) jun,
COALESCE([7], 0) jul,
COALESCE([8], 0) aug,
COALESCE([9], 0) sep,
COALESCE([10], 0) oct,
COALESCE([11], 0) nov,
COALESCE([12], 0) dec
FROM hour_list h LEFT JOIN
(
SELECT DATEPART(MONTH, logtime) month,
DATEPART(HOUR, logtime) hour,
COUNT(*) log_count
FROM somelog (NOLOCK)
GROUP BY DATEPART(MONTH, logtime), DATEPART(HOUR, logtime)
) s
PIVOT
(
SUM(log_count) FOR month IN([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])
) p
ON h.hour = p.hour
Sample output for both queries:
| HOUR | JAN | FEB | MAR | APR | MAY | JUN | JUL | AUG | SEP | OCT | NOV | DEC |
|------|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| 0 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 3 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 4 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
...
Here is SQLFiddle demo (using CASE)
Here is SQLFiddle demo (using PIVOT)

Pivot/aggregation with percentage columns possible in t-sql?

Struggling with this a bit in SQL Server, any ideas? Given this data (ID is an INT, the rest are BITs):
------------------------------------------
ID Type1 Type2 AttrA AttrB AttrC
------------------------------------------
1 1 0 1 0 0
2 1 0 1 0 0
3 1 1 0 1 1
4 0 1 1 1 0
5 1 1 1 1 0
I would like to produce this report:
---------------------------------------------------------
Attr NumOfType1 PctOfType1 NumOfType2 PctOfType2
---------------------------------------------------------
AttrA 3 75% 2 67%
AttrB 2 50% 3 100%
AttrC 1 25% 1 33%
Total 4 N/A 3 N/A
Thanks!
Jim
;WITH YourBaseTable AS
(
SELECT 1 ID, 1 Type1,0 Type2, 1 AttrA, 0 AttrB, 0 AttrC UNION ALL
SELECT 2 ID, 1 Type1,0 Type2, 1 AttrA, 0 AttrB, 0 AttrC UNION ALL
SELECT 3,1,1,0,1,1 UNION ALL
SELECT 4,0,1,1,1,0 UNION ALL
SELECT 5,1,1,1,1,0
), T AS
(
SELECT *, 1 AS Total
FROM YourBaseTable
)
SELECT
Attr,
COUNT(CASE WHEN VALUE = 1 AND Type1 = 1 THEN 1 END) NumOfType1,
CASE WHEN Attr <> 'Total' THEN 100 * CAST(COUNT(CASE WHEN VALUE = 1 AND Type1 = 1 THEN 1 END) AS FLOAT)/COUNT(CASE WHEN Type1 = 1 THEN 1 END) END PctOfType1,
COUNT(CASE WHEN VALUE = 1 AND Type2 = 1 THEN 1 END) NumOfType2,
CASE WHEN Attr <> 'Total' THEN 100 * CAST(COUNT(CASE WHEN VALUE = 1 AND Type2 = 1 THEN 1 END) AS FLOAT)/COUNT(CASE WHEN Type2 = 1 THEN 1 END) END PctOfType2
FROM T
UNPIVOT
(VALUE FOR Attr IN (AttrA, AttrB,AttrC, Total)) AS unpvt
GROUP BY Attr

Resources