Reputation: 171
I have a table (SQL Server 2008) with shipments, so "Stage 0" means "New shipment" and consecutive stages are diferent stages of shipment tracking.
I'm trying to pivot the following table:
CREATE TABLE TableName
([ID] int, [IDShip] int, [Date] datetime, [Stage] int, [Arg] int)
;
INSERT INTO TableName
([ID], [IDShip], [Date], [Stage], [Arg])
VALUES
(1, 1, '2013-10-03 08:36:00', 0, Null),
(2, 1, '2013-10-03 08:37:25', 1, 1),
(3, 2, '2013-10-03 08:38:25', 0, Null),
(4, 1, '2013-10-03 08:39:25', 2, 1),
(5, 2, '2013-10-03 08:40:25', 1, 3)
;
("Arg" is ID of Stage0. Select * would be:)
ID IDShip Date Stage Arg
1 1 2013-10-03 08:36:00 0 Null
2 1 2013-10-03 08:37:25 1 1
3 2 2013-10-03 08:38:25 0 Null
4 1 2013-10-03 08:39:25 2 1
5 2 2013-10-03 08:40:25 1 3
into something like:
ID0 IDShip DateShipment ID1 DateFirstStage ID2 DateSecondStage
1 1 2013-10-03 08:36:00 2 2013-10-03 08:37:25 4 2013-10-03 08:39:25
3 2 2013-10-03 08:38:25 5 2013-10-03 08:40:25
Any help? Thanks
Upvotes: 1
Views: 126
Reputation: 77657
It appears you need to pivot more than one column at the same time. However, standard PIVOT syntax does not support multi-columnar pivoting. You could use it to pivot one of the columns, then, using those as look-up values, pull the other column values with a series of correlated subqueries.
My take on the approach was similar to @Szymon's, except I managed to avoid grouping in the outer query, although I made things more messy at other stages. Here is my attempt:
SELECT
IDShip,
ID0,
ID1,
ID2,
DateShipment = (SELECT Date FROM TableName WHERE ID = p.ID0),
DateFirstStage = (SELECT Date FROM TableName WHERE ID = p.ID1),
DateSecondStage = (SELECT Date FROM TableName WHERE ID = p.ID2)
FROM (
SELECT
ID,
IDShip,
StageID = 'ID' + CAST(Stage AS varchar(10))
FROM TableName
) AS s
PIVOT (
MAX(ID) FOR StageID IN (ID0, ID1, ID2)
) AS p
;
With proper indexing, it may not be too bad, although you could also try this alternative, which uses the older pivoting technique of grouping with conditional aggregation:
SELECT
IDShip,
ID0 = MAX(CASE Stage WHEN 0 THEN ID END),
ID1 = MAX(CASE Stage WHEN 1 THEN ID END),
ID2 = MAX(CASE Stage WHEN 2 THEN ID END),
DateShipment = MAX(CASE Stage WHEN 0 THEN Date END),
DateFirstStage = MAX(CASE Stage WHEN 1 THEN Date END),
DateSecondStage = MAX(CASE Stage WHEN 2 THEN Date END)
FROM TableName
GROUP BY IDShip
;
This SQL Fiddle demo will let you try both solutions.
Upvotes: 0
Reputation: 43023
Turned out to be a bit more messy than I hoped for but here it is:
SELECT MAX([0]) AS ID0,
IDShip,
(SELECT [Date] FROM TableName T1 WHERE T1.ID = MAX([0]) AND T1.IDShip = Y.IDShip) AS DateShipment,
MAX([1]) AS ID1,
(SELECT [Date] FROM TableName T2 WHERE T2.ID = MAX([1]) AND T2.IDShip = Y.IDShip) AS DateFirstStage,
MAX([2]) AS ID2,
(SELECT [Date] FROM TableName T3 WHERE T3.ID = MAX([2]) AND T3.IDShip = Y.IDShip) AS DateSecondStage
FROM
(SELECT * FROM TableName
PIVOT (MAX([ID]) FOR Stage IN ([0], [1], [2])) AS X) Y
GROUP BY IDShip
You first pivot the table into ID's of 3 stages and then select each stage and its date.
Upvotes: 1