Convert Rows to columns using 'Pivot' Top 5 - sql-server

I want a pivot table from a SQL table with top 3 records only with filter based on user.
ID PrOjID User piD
------- ---- ------ ------
1 Prj1 ABC 1
2 Prj2 XYZ 2
3 Prj3 ABC 3
4 Prj4 ABC 4
5 Prj5 PQR 5
6 Prj1 XYZ 1
7 Prj3 PQR 3
8 Prj8 ABC 8
9 Prj1 PQR 1
10 Prj10 ABC 10
11 Prj11 ABC 11
12 Prj12 ABC 12
Result I want when user is ABC
ID1 PROJID1 piD1 ID2 PROJID2 piD2 ID3 PROJID3 piD3
1 prj1 1 3 PRJ3 3 4 prj4 4
If USER IS xyz
ID1 PROJID1 piD1 ID2 PROJID2 piD2 ID3 PROJID3 piD3
2 prj2 2 1 PRJ1 1 null null null

We can handle this using a pivot with the help of ROW_NUMBER:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY [User] ORDER BY piD) rn
FROM yourTable
)
SELECT
[User],
MAX(CASE WHEN rn = 1 THEN ID END) AS ID1,
MAX(CASE WHEN rn = 1 THEN PrOjID END) AS PROJID1,
MAX(CASE WHEN rn = 1 THEN piD END) AS piD1,
MAX(CASE WHEN rn = 2 THEN ID END) AS ID2,
MAX(CASE WHEN rn = 2 THEN PrOjID END) AS PROJID2,
MAX(CASE WHEN rn = 2 THEN piD END) AS piD2,
MAX(CASE WHEN rn = 3 THEN ID END) AS ID3,
MAX(CASE WHEN rn = 3 THEN PrOjID END) AS PROJID3,
MAX(CASE WHEN rn = 3 THEN piD END) AS piD3
FROM cte
WHERE
[User] = 'ABC'
GROUP BY
[User];
Demo

Related

Operand data type image is invalid for max operator in SQL Server 2014

I have a query that works in dev 2008 but does not work in test 2014.
I need the query returned in the exact format due to display requiremnts, but I don't know how to convert it. I tried casting and converting.
The error message i get on 2014 when i run the query is
Msg 8117, Level 16, State 1, Line 3
Operand data type image is invalid for max operator.
Here is the query:
SELECT Max(CASE
WHEN rn % 3 = 0 THEN itemtransactionbatchid
END) AS ItemTransactionBatchId,
Max(CASE
WHEN rn % 3 = 0 THEN referencebytes
END) AS ReferenceBytes,
Max(CASE
WHEN rn % 3 = 0 THEN description
END) AS Description,
Max(CASE
WHEN rn % 3 = 1 THEN itemtransactionbatchid
END) AS ItemTransactionBatchId1,
Max(CASE
WHEN rn % 3 = 1 THEN referencebytes
END) AS ReferenceBytes1,
Max(CASE
WHEN rn % 3 = 1 THEN description
END) AS Description1,
Max(CASE
WHEN rn % 3 = 2 THEN itemtransactionbatchid
END) AS ItemTransactionBatchId2,
Max(CASE
WHEN rn % 3 = 2 THEN referencebytes
END) AS ReferenceBytes2,
Max(CASE
WHEN rn % 3 = 2 THEN description
END) AS Description2
FROM (SELECT a.itemtransactionbatchid,
a.referencebytes,
b.description,
( ROW_NUMBER()
OVER(
ORDER BY CASE WHEN b.code='SIGOPRT' THEN 1 WHEN b.code='SIGDRVR' THEN 2 WHEN b.code='SIGTRANS' THEN 3 WHEN b.code='SIGRECV' THEN 4 WHEN b.code='SIGN' THEN 5 WHEN b.code='SIGSUPR' THEN 6 ELSE 0 END, b.code, (SELECT NULL)) - 1 ) rn
FROM [Transaction].itemtransactionref a (NOLOCK)
JOIN [Transaction].transactionreftype b
ON a.transactionreftypeid = b.transactionreftypeid
WHERE b.code IN( 'SIGDRVR', 'SIGN', 'SIGOPRT', 'SIGRECV',
'SIGSUPR', 'SIGTRANS' )
AND a.itemtransactionbatchid = xxxxxxx
AND referencebytes IS NOT NULL)x
GROUP BY rn / 3
Change the datatype of the image column to VARBINARY(MAX); MAX on that type is supported.
This does not give any errors:
CREATE TABLE #t(entr VARBINARY(MAX));
SELECT MAX(entr) FROM #t;

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

How to select PIVOT for this table?

I have a table like this:
Id Code Value
----------- -------------------- -----------
1 A 100
2 B 100
3 C 220
4 A 150
5 C 300
6 D 120
7 E 120
And this is my expectation:
Code1 Value1 Code2 Value2 Code3 Value3
----------- ----------- ----------- ----------- ----------- -----------
A 100 B 100 C 220
A 150 C 300 D 120
E 120
Should I use PIVOT to this case (and how to do this) or normal select query?
This isn't with pivot either, but in case you need to group the items into groups of 3 ordered by ID and the ID has gaps, like sometimes happen, this should do it:
select
ROW,
max(case when COL = 0 then Code end) as Code1,
max(case when COL = 0 then Value end) as Value1,
max(case when COL = 1 then Code end) as Code2,
max(case when COL = 1 then Value end) as Value2,
max(case when COL = 2 then Code end) as Code3,
max(case when COL = 2 then Value end) as Value3
FROM (
select
(row_number() over (order by ID)-1) % 3 as COL,
(row_number() over (order by ID)-1) / 3 as ROW,
Code,
Value
from
data
) X
group by ROW
This calculates row and column numbers based on row_number that increases over ID, and then uses group by to split the results into groups of 3.
SQL Fiddle
Perhaps PIVOT is not usefull here.
SELECT t1.code as code1, t1.value as value1,
t2.code as code2, t2.value as value2,
t3.code as code3, t3.value as value3
FROM tab as t1
left join tab as t2
ON t1.id = t2.id - 1
left join tab as t3
ON t2.id = t3.id - 1
where ((t1.id-1) % 3) = 0

Denormalize data for purchased items

I have the following table:
BoughtItems
UserID ItemID StoreID Quantity Price
1 1 1 1 1
1 4 1 2 3
1 5 2 1 3
Let's assume that it will be no more then five items for each user in BoughtItems table.
I want to have all the clients from some StoreID and all items that were purchased, in this format... for StoreID = 1 the result will be:
UserID Item1ID Item2ID Item3ID Item4ID Item5ID
1 1 4 [empty] [empty] [empty]
DECLARE #StoreID INT;
SET #StoreID = 1;
;WITH x AS
(
SELECT UserID, ItemID,
rn = ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY ItemID)
FROM dbo.BoughtItems
WHERE StoreID = #StoreID
)
SELECT UserID,
Item1ID = MAX(CASE WHEN rn = 1 THEN ItemID END),
Item2ID = MAX(CASE WHEN rn = 2 THEN ItemID END),
Item3ID = MAX(CASE WHEN rn = 3 THEN ItemID END),
Item4ID = MAX(CASE WHEN rn = 4 THEN ItemID END),
Item5ID = MAX(CASE WHEN rn = 5 THEN ItemID END)
FROM x WHERE rn <= 5
GROUP BY UserID;

Resources