Denormalize data for purchased items - sql-server

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;

Related

SQL Challenge concatenate rows to the end of every group

I have the following table and I need to flatten the data.
From here
table 1
id val1 val2 ....valn
-----------------------------------
1 a z
1 b x
1 c v
2 a w
2 b q
..n
To here
id val1_1 val2_1 ....valn_1 val1_2 val2_2 ... valn_2 .... val1_n...valn_n
-----------------------------------
1 a z b x
2 a w b q
..n
Any ideas?
I have done something using cursors, however it is a little nasty and It has some bugs. Pivot?
Yes you need to a pivot, but you also need to calculate a row-number to pivot against. However, given this is a multi-column pivot, it's probably easier to just use conditional aggregation.
I suggest you pick a proper ordering for the row-number
SELECT
id,
val1_1 = MAX(CASE WHEN t.rn = 1 THEN t.val1 END),
val2_1 = MAX(CASE WHEN t.rn = 1 THEN t.val2 END),
val3_1 = MAX(CASE WHEN t.rn = 1 THEN t.val3 END),
-- ...........
val1_2 = MAX(CASE WHEN t.rn = 2 THEN t.val1 END),
val2_2 = MAX(CASE WHEN t.rn = 2 THEN t.val2 END),
val3_2 = MAX(CASE WHEN t.rn = 2 THEN t.val3 END),
-- ...........
FROM (
SELECT *,
rn = ROW_NUMBER() OVER (PARTITION BY t.rn ORDER BY (SELECT 1))
FROM table1 t
) t
GROUP BY t.id;

How to pivot table from multiple column to multiple rows

CodeDt CodeHeader Item Qty Type Remark Attachment
LK4-033502 RK-K-LK4-032438 IA01001023 2.00 TPR002 2 1.jpeg
LK4-033502RK RK-K-LK4-032438 IA01001023RK 2.00 NULL IA01001023 NULL
Above is my data from Sql server table (using 2008 R2). I want to make it one row only. Here is my expected result:
CodeDt CodeHeader Item NewItem Qty
LK4-033502 RK-K-LK4-032438 IA01001023 IA01001023RK 2.00
How can I achieve that? Here is the relation:
Row 1 Item = Row 2 Remark,
Row 1 Code DT = Row 2 CodeDt+'RK'
There are several solutions
1) Using JOIN. It assumes that Type field is null for rows with CodeDt+'RK'
select
a.CodeDt, a.CodeHeader, a.Item, b.Item, a.Qty
from
myTable a
join myTable b on a.Item = b.Remark
where
a.Type is not null
2) Conditional aggregation
select
max(case when rn = 1 then CodeDt end)
, CodeHeader
, max(case when rn = 1 then Item end)
, max(case when rn = 2 then Item end)
, max(case when rn = 1 then Qty end)
from (
select
*, rn = row_number() over (partition by CodeHeader order by CodeDt)
from
myTable
) t
group by CodeHeader

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

SQL Server : convert rows to one row

I know SQL Server Pivot, but this time I think I will need something more complex then a simple pivoted value.
Here it is an SQL fiddle example.
So I have a table where I have maximum 3 rows for one startcity - endcity combination.
In a query I need to get these combinations in just one row, and I need just those combinations, where there are 3 rows.
Please advice,
You can do this as a crosstab like this.
with NumberedValues as
(
SELECT EndCity
, StartDate
, EndDate
, Price
, ROW_NUMBER() OVER(PARTITION BY StartCity, EndCIty ORDER BY StartDate) as RowNum
FROM [dbo].[BestPrice]
)
SELECT EndCity,
max(CASE WHEN RowNum = 1 THEN StartDate END) as StartDate1,
max(CASE WHEN RowNum = 1 THEN Enddate END) as EndDate1,
max(CASE WHEN RowNum = 1 THEN Price END) as Price1,
max(CASE WHEN RowNum = 2 THEN StartDate END) as StartDate2,
max(CASE WHEN RowNum = 2 THEN Enddate END) as EndDate2,
max(CASE WHEN RowNum = 2 THEN Price END) as Price2,
max(CASE WHEN RowNum = 3 THEN StartDate END) as StartDate3,
max(CASE WHEN RowNum = 3 THEN Enddate END) as EndDate3,
max(CASE WHEN RowNum = 3 THEN Price END) as Price3
FROM NumberedValues
group by EndCity

Resources