T-SQL Pivot multiple columns duplicates results - sql-server

I have a table with aggregated data that I would like to pivot. Here is a sample of the data:
Unit# EffectiveDay RequestCount ResponseCount
5 1 0 0
5 2 8 8
5 3 4 4
5 4 4 4
5 5 2 2
5 6 0 0
5 7 2 2
6 1 0 0
6 2 0 0
6 3 0 0
6 4 0 0
6 5 0 0
6 6 0 0
6 7 0 0
I can successfully pivot the RequestCount column, but when I add the ResponseCount column it's as if the rows increased exponentially. Instead of two rows (one for each unit#), I get 14.
select *
from (
select Unit#
,concat('Request', EffectiveDay) AS RequestDay
,RequestCount
,concat('Response', EffectiveDay) As ResponseDay
,ResponseCount
from #tmpLogPayConnexion
) as P
pivot (
sum(RequestCount)
for RequestDay in ([Request1], [Request2], [Request3], [Request4], [Request5], [Request6], [Request7])
) as pvtRequest
pivot (
sum(ResponseCount)
for ResponseDay in ([Response1], [Response2], [Response3], [Response4], [Response5], [Response6], [Response7])
) as pvtResponse
I know this is possible, but I am stumped.
Thank you.

This seems like a time for a crosstab, or conditional aggregation.
select [Unit#]
, Request1 = max(case when EffectiveDay = 1 then RequestCount end)
, Request2 = max(case when EffectiveDay = 2 then RequestCount end)
, Request3 = max(case when EffectiveDay = 3 then RequestCount end)
, Request4 = max(case when EffectiveDay = 4 then RequestCount end)
, Request5 = max(case when EffectiveDay = 5 then RequestCount end)
, Request6 = max(case when EffectiveDay = 6 then RequestCount end)
, Request7 = max(case when EffectiveDay = 7 then RequestCount end)
, Response1 = max(case when EffectiveDay = 1 then ResponseCount end)
, Response2 = max(case when EffectiveDay = 2 then ResponseCount end)
, Response3 = max(case when EffectiveDay = 3 then ResponseCount end)
, Response4 = max(case when EffectiveDay = 4 then ResponseCount end)
, Response5 = max(case when EffectiveDay = 5 then ResponseCount end)
, Response6 = max(case when EffectiveDay = 6 then ResponseCount end)
, Response7 = max(case when EffectiveDay = 7 then ResponseCount end)
from #tmpLogPayConnexion
group by [Unit#]
order by [Unit#]

Related

Monthly and Yearly Report in one row

I have a table whose output is this
i have written my query like this
SELECT
c.DivisionNameEn,
a.LF_CompanyDivisionID,
0 as code,
SUM(a.totInvoiceAmnt) AS Sales,
'Sales' Salesperson,
sum(a.totInvoiceAmnt) as Sum ,
sum(a.totInvoiceAmnt) /sum(a.totInvoiceAmnt) *100 as MonthPercent ,
YEAR(a.TransactionDate) [Year],
MONTH(a.TransactionDate) [Month],
CASE
WHEN datepart(month,a.TransactionDate) = 1 THEN SUM(CASE datepart(month,a.TransactionDate) WHEN 1 THEN 1 ELSE 0 END)
WHEN datepart(month,a.TransactionDate) = 2 THEN SUM(CASE datepart(month,a.TransactionDate) WHEN 2 THEN 1 ELSE 0 END)
WHEN datepart(month,a.TransactionDate) = 3 THEN SUM(CASE datepart(month,a.TransactionDate) WHEN 3 THEN 1 ELSE 0 END)
WHEN datepart(month,a.TransactionDate) = 4 THEN SUM(CASE datepart(month,a.TransactionDate) WHEN 3 THEN 1 ELSE 0 END)
WHEN datepart(month,a.TransactionDate) = 5 THEN SUM(CASE datepart(month,a.TransactionDate) WHEN 3 THEN 1 ELSE 0 END)
WHEN datepart(month,a.TransactionDate) = 6 THEN SUM(CASE datepart(month,a.TransactionDate) WHEN 3 THEN 1 ELSE 0 END)
WHEN datepart(month,a.TransactionDate) = 7 THEN SUM(CASE datepart(month,a.TransactionDate) WHEN 3 THEN 1 ELSE 0 END)
WHEN datepart(month,a.TransactionDate) = 8 THEN SUM(CASE datepart(month,a.TransactionDate) WHEN 3 THEN 1 ELSE 0 END)
WHEN datepart(month,a.TransactionDate) = 9 THEN SUM(CASE datepart(month,a.TransactionDate) WHEN 3 THEN 1 ELSE 0 END)
WHEN datepart(month,a.TransactionDate) = 10 THEN SUM(CASE datepart(month,a.TransactionDate) WHEN 10 THEN 1 ELSE 0 END)
WHEN datepart(month,a.TransactionDate) = 11 THEN SUM(CASE datepart(month,a.TransactionDate) WHEN 3 THEN 1 ELSE 0 END)
WHEN datepart(month,a.TransactionDate) = 12 THEN SUM(CASE datepart(month,a.TransactionDate) WHEN 3 THEN 1 ELSE 0 END)
ELSE 0
END as MonthTotal
from POS_salesHeader a
INNER JOIN dbo.STR_CompanyDivision AS c ON c.id = a.LF_CompanyDivisionID
--WHERE YEAR(a.TransactionDate) = YEAR(GETDATE()) AND MONTH(a.TransactionDate) = MONTH(GETDATE()) /*To filter by month*/
GROUP BY YEAR(a.TransactionDate), MONTH(a.TransactionDate) , c.DivisionNameEn ,LF_CompanyDivisionID
it is giving me out put like this
I want a row which give me month Total totInvoiceAmnt and till now Year Total totInvoiceAmnt for example if today its 15th April it gives me total totInvoiceAmnt of only April with the column name MonthsTotal and in another column it give me till now yearly totInvoiceAmnt total from month of jan + Feb + March +April

Unexpected inner join behavior

I've a query :
select TABLE.NAME,
max(case when TABLE_ADDITION.CODE= 1 then TABLE_ADDITION.VALUE end) Mach1,
max(case when TABLE_ADDITION.CODE= 4 then TABLE_ADDITION.VALUE end) Source,
max(case when TABLE_ADDITION.CODE= 6 then TABLE_ADDITION.VALUE end) Dest,
max(case when TABLE_ADDITION.CODE= 16 then TABLE_ADDITION.VALUE end) Mach2
FROM TABLE
This is working, the result is :
NAME Mach1 Source Dest Mach2
test 11 testS testD 12
I need another information from another table (MACH). Columns Mach1 and mach2 are IDs. I want to use this ID to take the name from the correct table MACH (see data below - end of the post).
I want to have :
NAME Mach1 Source Dest Mach2
test machName11 testS testD machName12
For that, I did :
select TABLE.NAME,
max(case when TABLE_ADDITION.CODE= 1 then MACH.MACHNAME end) Mach1,
max(case when TABLE_ADDITION.CODE= 4 then TABLE_ADDITION.VALUE end) Source,
max(case when TABLE_ADDITION.CODE= 6 then TABLE_ADDITION.VALUE end) Dest,
max(case when TABLE_ADDITION.CODE= 16 then MACH.MACHNAME end) Mach2
FROM TABLE
INNER JOIN TABLE_ADDITION ON TABLE.TABLEID = TABLE_ADDITION.TABLEID AND TABLE.NAME = TABLE_ADDITION.NAME
INNER JOIN MACH ON TABLE_ADDITION.CODE IN (1, 16) AND TABLE_ADDITION .VALUE = MACH.MACHID
However, I didn't receive my expected behavior :
NAME Mach1 Source Dest Mach2
test machName11 NULL NULL machName12
I tried for LEFT JOIN and INNER JOIN.
Data for TABLE_ADDITION :
TABLEID NAME CODE VALUE
1 test 1 11
1 test 4 testS
1 test 6 testD
1 test 16 12
1 test 20 value11
1 test 25 45
1 test ... [continue with a lot of ID and VALUE are int or varchar]
2 test2 1 45
2 test2 4 testSource\test
2 test2 6 testDest\test
2 test2 16 1
2 test2 20 value
2 test2 25 76
[continue for other ID]
For MACH
MACHID MACHNAME MACHTYPE
0 test 0
3 test1 1
10 test3 2
11 machName11 2
12 machName12 2
[continue with other ID]
For TABLE
TABLEID NAME TABLETYPE
1 test 12
1 test3 12
2 name 5
[continue with other ID]
I need the TABLE because it's my main table (with other column), I select some of them without issue.
EDIT, I edit my post, it was wrong and missing too much data to understand my issue.
For now it's working because I added one join :
select TABLE.NAME,
max(case when t2.CODE= 1 then MACH.MACHNAME end) Mach1,
max(case when TABLE_ADDITION.CODE= 4 then TABLE_ADDITION.VALUE end) Source,
max(case when TABLE_ADDITION.CODE= 6 then TABLE_ADDITION.VALUE end) Dest,
max(case when t2.CODE= 16 then MACH.MACHNAME end) Mach2
FROM TABLE
INNER JOIN TABLE_ADDITION ON TABLE.TABLEID = TABLE_ADDITION.TABLEID AND TABLE.NAME = TABLE_ADDITION.NAME
INNER JOIN TABLE_ADDITION t2 ON TABLE.TABLEID = t2 .TABLEID AND TABLE.NAME = t2 .NAME
INNER JOIN MACH ON t2 .CODE IN (1, 16) AND t2 .VALUE = MACH.MACHID
Thanks

convert multiple record to single record using sql query for 10 lac data

I have a table like
ID paper_Code Grade
-----------------------------------------------------------------
1 101 A+
1 102 B
1 103 C+
2 102 D
3 103 A
2 105 B
....
I need output like
Id P1 P2 P3
----------------------------------------------------------
1 101-A+ 102-B 103-C+
2 102-D 105-B
3 103-A
Thank you for co-operation.
Assuming your testing database looks like:
Here are options you might be interested in:
SELECT PaperId,
MAX(CASE WHEN Val = '101 A+' THEN Val END) [101 A+],
MAX(CASE WHEN Val = '102 B' THEN Val END) [102 B],
MAX(CASE WHEN Val = '103 C+' THEN Val END) [103 C+],
MAX(CASE WHEN Val = '102 D' THEN Val END) [102 D]
FROM Paper
GROUP BY PaperId
And the other way:
SELECT Val,
MAX(CASE WHEN PaperId = 1 THEN 'yes' END) '1',
MAX(CASE WHEN PaperId = 2 THEN 'yes' END) '2',
MAX(CASE WHEN PaperId = 3 THEN 'yes' END) '3'
FROM Paper
GROUP BY Val

How to fetch record from two tables specify column name based on second table row records

I need query which fetch records from two tables but column name should be based on records in second table.
Details are below
My first table
Emp Table
emp_id emp_name
1 Abc
2 XYZ
3 PQR
My second table
Salary Table
id emp_id month salary
1 1 1 4000
2 1 2 3000
3 2 1 5000
4 2 2 4500
I need output like,
emp_id emp_name jan feb
1 Abc 4000 3000
2 XYZ 5000 4500
I am able to achieve this by using left join but for every month I need to add it in query like,
select e.emp_id,e.emp_name,j.month as Jan,f.month as Feb from emp e
Left Join salary j on e.emp_id=j.emp_id and j.month=1
Left Join salary f on e.emp_id=f.emp_id and f.month=2
Above work for me But which is not feasible. I have master table for month also.
Month Table
id Name
1 Jan
2 Feb
3 March
5 April
I want fetch record for for specific month currently for (Jan & feb).
Please help me achieve this faster way.
Using conditional aggregation:
SELECT
e.emp_id,
e.emp_name,
[Jan] = MAX(CASE WHEN s.[month] = 1 THEN s.salary END),
[Feb] = MAX(CASE WHEN s.[month] = 2 THEN s.salary END),
[Mar] = MAX(CASE WHEN s.[month] = 3 THEN s.salary END),
[Apr] = MAX(CASE WHEN s.[month] = 4 THEN s.salary END),
[May] = MAX(CASE WHEN s.[month] = 5 THEN s.salary END),
[Jun] = MAX(CASE WHEN s.[month] = 6 THEN s.salary END),
[Jul] = MAX(CASE WHEN s.[month] = 7 THEN s.salary END),
[Aug] = MAX(CASE WHEN s.[month] = 8 THEN s.salary END),
[Sep] = MAX(CASE WHEN s.[month] = 9 THEN s.salary END),
[Oct] = MAX(CASE WHEN s.[month] = 10 THEN s.salary END),
[Nov] = MAX(CASE WHEN s.[month] = 11 THEN s.salary END),
[Dec] = MAX(CASE WHEN s.[month] = 12 THEN s.salary END)
FROM Emp e
LEFT JOIN Salary s
ON s.emp_id = e.emp_id
GROUP BY
e.emp_id, e.emp_name
ONLINE DEMO

Summary Query in SQL Server

I have following data
ID Status
5bcb5961-20e-41b7-8af0-87ffe127830c 1
140c7f17-dba5-4bc8-1fb-062d1325c399 5
5bcb5961-20e-41b7-8af0-87ffe127830c 5
5bcb5961-20e-41b7-8af0-87ffe127830c 0
I want an output in summary form.
ID Status_1 Status_5 Status_0
5bcb5961-d20e-41b7-8af0-87ffe127830c 1 1 1
140c7f17-dba5-4bc8-b1fb-062d1325c399 0 1 0
Can I get query for this output?
SELECT
ID
, Status_1 = COUNT(CASE WHEN [Status] = 1 THEN 1 END)
, Status_5 = COUNT(CASE WHEN [Status] = 5 THEN 1 END)
, Status_0 = COUNT(CASE WHEN [Status] = 0 THEN 1 END)
FROM tbl
GROUP BY ID

Resources