SQL PIVOT on a variable amount of rows - sql-server

I have the following data on a MSSQL Server:
Item No_ Unit Of Measure Qty Per Base UoM Rounding Precision
000001 PIECE 1 1.0
000001 PALLET 100 1.0
000001 BOX 12 1.0
000002 KG 1 1.0
000002 TON 1000 0.001
I am trying to get the following output:
Item No_ UoM1 Qty pb UoM1 RP1 UoM2 Qty pb UoM2 RP2 UoM3 Qty pb UoM3 RP3
000001 PIECE 1 1.0 PALLET 100 1.0 BOX 12 1.0
000002 KG 1 1.0 TON 1000 0.0001 NULL NULL NULL
I tried achieving this using the PIVOT operator but it does not seem te be correct.
What is the correct way to achieve my desired output?

For trully generic solution you need to use Dynamic-SQL.
But you say you want starting point, so I give you one. You can use:
LiveDemo
WITH cte AS
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY Item_No_ ORDER BY (SELECT 1)) AS rn
FROM #mytable
)
select Item_No_,
max(case when rn = 1 then Unit_Of_Measure end) UoM1,
max(case when rn = 1 then Qty_Per_Base_UoM end) [Qty pb UoM1],
max(case when rn = 1 then Rounding_Precision end) RP1,
max(case when rn = 2 then Unit_Of_Measure end) UoM2,
max(case when rn = 2 then Qty_Per_Base_UoM end) [Qty pb UoM2],
max(case when rn = 2 then Rounding_Precision end) RP2,
max(case when rn = 3 then Unit_Of_Measure end) UoM3,
max(case when rn = 3 then Qty_Per_Base_UoM end) [Qty pb UoM3],
max(case when rn = 3 then Rounding_Precision end) RP3,
max(case when rn = 4 then Unit_Of_Measure end) UoM4,
max(case when rn = 4 then Qty_Per_Base_UoM end) [Qty pb UoM4],
max(case when rn = 4 then Rounding_Precision end) RP4
from cte
group by Item_No_;
The point is that if your number of units is known in advance you can create hardcoded columns from 1 .. n.
For more info search Dynamic Pivot multiple columns. It is achievable, but first try to crack this solution.

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;

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

Help with finding the difference (delta) from a value returned from the last two records

I'm using MS SQL 2005 and I have created a CTE query to return values from the last two records. I then use this to find the delta of two figures returned. I have a working query of sorts but
I'm having problems getting anything other than the delta figure.
here is my query:
;with data as(
SELECT
NetObjectID,
RawStatus,
RowID,
rn
from(
SELECT
CustomPollerAssignmentID AS NetObjectID,
RawStatus,
RowID,
row_number() over(order by DateTime desc)as rn
FROM CustomPollerStatistics_Detail
WHERE
(CustomPollerAssignmentID='a87f531d-4842-4bb3-9d68-7fd118004356')
) x where rn<=2
)
SELECT
case when
max(case rn when 1 then RawStatus end) > max(case rn when 2 then RawStatus end)
then
max(case rn when 1 then RawStatus end) - max(case rn when 2 then RawStatus end)
else
max(case rn when 2 then RawStatus end) - max(case rn when 1 then RawStatus end)
end as Delta
from data having
(SELECT
case when
max(case rn when 1 then RawStatus end) > max(case rn when 2 then RawStatus end)
then
max(case rn when 1 then RawStatus end) - max(case rn when 2 then RawStatus end)
else
max(case rn when 2 then RawStatus end) - max(case rn when 1 then RawStatus end)
end
from data) >= 1
What I'm after is to get the Delta & NetObjectID returned. Each time I try, I get errors.
data.NetObjectID is invalid in the select list because it is not contained in either an aggregate function or the group by clause.
If I try adding group by etc.. to the end of the query I get further error complaining about the word 'group'.
I'm relatively new to SQL and I am picking things up as I go. Any help would be gratefully received.
see if something like this will work.
;with data as
(
SELECT
NetObjectID,
RawStatus,
RowID,
rn
from
(
SELECT
CustomPollerAssignmentID AS NetObjectID,
RawStatus,
RowID,
row_number() over(order by DateTime desc)as rn
FROM CustomPollerStatistics_Detail
WHERE
(
CustomPollerAssignmentID='a87f531d-4842-4bb3-9d68-7fd118004356'
)
) x
where rn<=2
)
select
NetObjectID,
max(RawStatus)-min(RawStatus) as Delta
from data
group by NetObjectID
Sorry, I'm very new here and I'm unsure of CTE queries, however it looks like after you define Data, you are selecting case ... as Delta FROM.... Meaning you only have Delta in your select statement. Again, sorry if I'm way off base.

Resources