I have a source table that looks like this:
+--------------+----------+------+------------+-----------+
| vehicleindex | parentid | year | make | model |
+--------------+----------+------+------------+-----------+
| 1 | 1 | 2007 | TOYOTA | SIENNA LE |
| 2 | 1 | 2005 | VOLKSWAGEN | JETTA GLS |
+--------------+----------+------+------------+-----------+
I'd like to select from this table such that the output looks like this:
+-------+--------+-----------+-------+------------+-----------+
| year1 | make1 | model1 | year2 | make2 | model2 |
+-------+--------+-----------+-------+------------+-----------+
| 2007 | TOYOTA | SIELLA LE | 2005 | VOLKSWAGEN | JETTA GLS |
+-------+--------+-----------+-------+------------+-----------+
How can I accomplish this on a SQL Server database with a pivot? There will always be either 1 or 2 vehicles in the source table. In the case where there's 1 vehicle, I would expect Year2, Make2 and Model2 to be NULL.
Similar to SQLZim's answer. Only difference is that the Window function Row_Number() is used just in case vehicleindex is not a consistent 1 and 2.
Select year1 = max(case when RN=1 then [year] end)
,make1 = max(case when RN=1 then make end)
,model1 = max(case when RN=1 then model end)
,year2 = max(case when RN=2 then [year] end)
,make2 = max(case when RN=2 then make end)
,model2 = max(case when RN=2 then model end)
From (
Select *
,RN = Row_Number() over (Partition By parentid Order By vehicleindex)
From YourTable
) A
Group By parentid
EDIT: Option 2 - Use PIVOT
Select *
From (
Select parentid
,item = concat(B.item,Dense_Rank() over (Partition By parentid Order By vehicleindex))
,value
From YourTable
Cross Apply ( values ('year' ,cast(Year as varchar(100)))
,('make' ,make)
,('model',model)
) B (item,value)
) A
Pivot (max(value) For [item] in ([year1],[make1],[model1],[year2],[make2],[model2]) ) p
Using conditional aggregation:
select
parentid
, year1 = max(case when vehicleindex=1 then [year] end)
, make1 = max(case when vehicleindex=1 then make end)
, model1 = max(case when vehicleindex=1 then model end)
, year2 = max(case when vehicleindex=2 then [year] end)
, make2 = max(case when vehicleindex=2 then make end)
, model2 = max(case when vehicleindex=2 then model end)
from t
group by parentid
returns:
+----------+-------+------------+-----------+-------+------------+-----------+
| parentid | year1 | make1 | model1 | year2 | make2 | model2 |
+----------+-------+------------+-----------+-------+------------+-----------+
| 1 | 2007 | TOYOTA | SIENNA LE | 2005 | VOLKSWAGEN | JETTA GLS |
| 2 | 2018 | TESLA | MODEL 3 | NULL | NULL | NULL |
+----------+-------+------------+-----------+-------+------------+-----------+
rextestder demo: http://rextester.com/ZTGXU25389
using this test data:
create table t (
vehicleindex int
, parentid int
, [year] int
, make varchar(32)
, model varchar(32)
);
insert into t values
(1,1,2007,'TOYOTA ','SIENNA LE')
, (2,1,2005,'VOLKSWAGEN','JETTA GLS')
, (1,2,2018,'TESLA','MODEL 3')
Unfortunately if you need to pivot 3 columns you need to create 3 separate pivots, then merge them in the end:
SELECT MAX(Year1) as 'Year1', MAX(Make1) as Make1, MAX(Model1) as 'Model1',
MAX(Year2) as 'Year2', MAX(Make2) as Make2, MAX(Model2) as 'Model2'
FROM
(
SELECT parentid,
[1] as 'Year1', NULL as Make1, NULL as 'model1',
[2] as 'Year2', NULL as Make2, NULL as 'model2'
FROM (
SELECT
parentid, vehicleindex, model, make , [year]
FROM #temp
) as s
PIVOT
(
max([year])
FOR vehicleindex IN ([1],[2])
) AS yearPvt
UNION
SELECT parentid,
NULL as 'Year1', [1] as Make1, NULL as 'model1',
NULL as 'Year2', [2] as Make2, NULL as 'model2'
FROM
(
SELECT
parentid, vehicleindex, model, make , [year]
FROM #temp
) as s
parentid, vehicleindex, model, make , [year]
FROM #temp
) as s
PIVOT
(
MAX([make])
FOR vehicleindex IN ([1],[2])
)AS makePvt
UNION
SELECT parentid,
NULL as 'Year1', NULL as Make1, [1] as 'model1',
NULL as 'Year2', NULL as Make2, [2] as 'model2'
FROM
(
SELECT
parentid, vehicleindex, model, make , [year]
FROM #temp
) as s
PIVOT
(
max([model])
FOR vehicleindex IN ([1],[2])
) AS modelPvt
) allPivots
Group BY parentid
Related
I've spent much too long trying to figure out how TSQL pivoting works, so I'm posting this hoping someone that understands pivots can help me.
So here's a representative source result set:
Notice that there are only 3 rows, but that's still <=4.
| Code | Date |
|-------|------------|
| 12345 | 2018-01-01 |
| 67890 | NULL |
| 13579 | 2018-01-02 |
This is target result set I want from the source result set:
| Code_1 | Date_1 | Code_2 | Date_2 | Code_3 | Date_3 | Code_4 | Date_4 |
|--------|------------|--------|--------|--------|------------|--------|--------|
| 12345 | 2018-01-01 | 67890 | NULL | 13579 | 2018-01-02 | NULL | NULL |
Here's something that does literally what you're asking by joining 2 pivot queries together:
DECLARE #tbl TABLE (code INT, dt DATETIME)
INSERT INTO #tbl VALUES (12345, '1/1/2018')
INSERT INTO #tbl VALUES (67890, null)
INSERT INTO #tbl VALUES (13579, '1/1/2018')
SELECT SQ1.Code_1, SQ2.Code_1, SQ1.Code_2, SQ2.Code_2, SQ1.Code_3, SQ2.Code_3, SQ1.Code_4, SQ2.Code_4
FROM
(
SELECT [Code_1], [Code_2], [Code_3], [Code_4]
FROM
(
SELECT 'Code_' + CAST(ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS VARCHAR(3)) AS RowID, code FROM #tbl
) source
PIVOT
(
MAX(code)
FOR RowID IN ([Code_1], [Code_2], [Code_3], [Code_4])
)sq
)SQ1
CROSS APPLY
(
SELECT [Code_1], [Code_2], [Code_3], [Code_4]
FROM
(
SELECT 'Code_' + CAST(ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS VARCHAR(3)) AS RowID, dt FROM #tbl
) source
PIVOT
(
MAX(dt)
FOR RowID IN ([Code_1], [Code_2], [Code_3], [Code_4])
)sq
)SQ2
Outputs:
Code_1 Code_1 Code_2 Code_2 Code_3 Code_3 Code_4 Code_4
12345 2018-01-01 67890 NULL 13579 2018-01-01 NULL NULL
Assuming you want a max of 4 groups (8 columns).
You may also notice that in the Order By I use (Select null). Without a proper sequence key, there is no gtd of order.
Example
Select Code_1 = max(case when Col=1 then Code end)
,Date_1 = max(case when Col=1 then Date end)
,Code_2 = max(case when Col=2 then Code end)
,Date_2 = max(case when Col=2 then Date end)
,Code_3 = max(case when Col=3 then Code end)
,Date_3 = max(case when Col=3 then Date end)
,Code_4 = max(case when Col=4 then Code end)
,Date_4 = max(case when Col=4 then Date end)
From (
Select *
,Col = Row_Number() over (Order by (Select null))
From #YourTable
) A
Returns
Code_1 Date_1 Code_2 Date_2 Code_3 Date_3 Code_4 Date_4
12345 2018-01-01 67890 NULL 13579 2018-01-01 NULL NULL
I have a Documents table and an Events table.
Documents table has ID and a bunch of other fields not relevant to
this question.
Events table has DocID, EventType, EventDate, and UserID.
A document may have zero or more Events of any of these EventTypes:
0 = Created
1 = Modified
2 = Submitted
3 = Approved
DocID | EventType | EventDate | UserID
-----------------------------------------------
1 | 0 | 1-2-2017 | 123
1 | 1 | 1-3-2017 | 456
1 | 1 | 1-4-2017 | 489
1 | 2 | 1-5-2017 | 357
2 | 0 | 1-6-2017 | 951
2 | 1 | 1-7-2017 | 654
2 | 2 | 1-8-2017 | 654
2 | 3 | 1-9-2017 | 357
Pivoting the Events table is easy enough:
SELECT DocID, [0] AS CreatedDate, [1] AS ModifiedDate,
[2] AS SubmittedDate, [3] AS ApprovedDate
FROM (SELECT DocID, EventType, EventDate FROM Events
WHERE DocID IS NOT NULL AND EventDate IS NOT NULL) AS DocEvents
PIVOT (MAX(EventDate) FOR EventType IN ([0], [1], [2], [3]))
AS DocEventsPivot
For my purposes, the most recent event of a given type is wanted, thus the MAX aggregate:
DocID | CreatedDate | ModifiedDate | SubmittedDate | ApprovedDate
-----------------------------------------------------------------
1 | 1-2-2017 | 1-4-2017 | 1-5-2017 | NULL
2 | 1-6-2017 | 1-7-2017 | 1-8-2017 | 1-9-2017
How can I get the UserID translated to CreatedBy, ModifiedBy, SubmittedBy, and ApprovedBy to correspond to the dates of the appropriate EventType?
I will not know the possible values of UserID in advance.
Desired Output:
DocID | CreatedDate | ModifiedDate | SubmittedDate | ApprovedDate | CreatedBy | ModifiedBy | SubmittedBy | ApprovedBy
---------------------------------------------------------------------------------------------------------------------
1 | 1-2-2017 | 1-4-2017 | 1-5-2017 | NULL | 123 | 489 | 357 | NULL
2 | 1-6-2017 | 1-7-2017 | 1-8-2017 | 1-9-2017 | 951 | 654 | 654 | 657
Rather than using PIVOT another solution is using OUTER APPLY.
CREATE TABLE #Documents (ID int)
CREATE TABLE #Events (DocID int, EventType int, EventDate date, UserID int)
INSERT INTO #Documents VALUES
(1),
(2)
INSERT INTO #Events VALUES
(1, 0, '1-2-2017', 123),
(1, 1, '1-3-2017', 456),
(1, 1, '1-4-2017', 489),
(1, 2, '1-5-2017', 357),
(2, 0, '1-6-2017', 951),
(2, 1, '1-7-2017', 654),
(2, 2, '1-8-2017', 654),
(2, 3, '1-9-2017', 357)
SELECT
DOC.ID AS 'DocID',
CRT.EventDate AS 'CreatedDate',
MFY.EventDate AS 'ModifiedDate',
SUB.EventDate AS 'SubmittedDate',
APR.EventDate AS 'ApprovedDate',
CRT.UserID AS 'CreatedBy',
MFY.UserID AS 'ModifiedBy',
SUB.UserID AS 'SubmittedBy',
APR.UserID AS 'ApprovedBy'
FROM
#Documents AS DOC
OUTER APPLY (SELECT TOP 1 EventDate, UserID FROM #Events WHERE DocID = DOC.ID AND EventType = 0 ORDER BY EventDate DESC) AS CRT
OUTER APPLY (SELECT TOP 1 EventDate, UserID FROM #Events WHERE DocID = DOC.ID AND EventType = 1 ORDER BY EventDate DESC) AS MFY
OUTER APPLY (SELECT TOP 1 EventDate, UserID FROM #Events WHERE DocID = DOC.ID AND EventType = 2 ORDER BY EventDate DESC) AS SUB
OUTER APPLY (SELECT TOP 1 EventDate, UserID FROM #Events WHERE DocID = DOC.ID AND EventType = 3 ORDER BY EventDate DESC) AS APR
DROP TABLE #Documents
DROP TABLE #Events
Try the following
CREATE TABLE #Events (DocID int, EventType int, EventDate date, UserID int)
INSERT INTO #Events VALUES
(1, 0, '1-2-2017', 123),
(1, 1, '1-3-2017', 456),
(1, 1, '1-4-2017', 489),
(1, 2, '1-5-2017', 357),
(1, 2, '1-4-2017', 666),
(2, 0, '1-6-2017', 951),
(2, 1, '1-7-2017', 654),
(2, 2, '1-8-2017', 654),
(2, 3, '1-9-2017', 357)
SELECT
DocID,
MAX(CASE WHEN EventType=0 THEN EventDate END) [CreatedDate],
MAX(CASE WHEN EventType=1 THEN EventDate END) [ModifiedDate],
MAX(CASE WHEN EventType=2 THEN EventDate END) [SubmittedDate],
MAX(CASE WHEN EventType=3 THEN EventDate END) [ApprovedDate],
MAX(CASE WHEN EventType=0 THEN LastUserID END) [CreatedBy],
MAX(CASE WHEN EventType=1 THEN LastUserID END) [ModifiedBy],
MAX(CASE WHEN EventType=2 THEN LastUserID END) [SubmittedBy],
MAX(CASE WHEN EventType=3 THEN LastUserID END) [ApprovedBy]
FROM
(
SELECT
DocID,
EventDate,
EventType,
LAST_VALUE(UserID)OVER(
PARTITION BY DocID,EventType
ORDER BY EventDate
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
) LastUserID
FROM #Events
) q
GROUP BY DocID
DROP TABLE #Events
Or you can use IFF instead CASE. I prefer use CASE because it isn't block ELSE
SELECT
DocID,
MAX(IIF(EventType=0,EventDate,NULL)) [CreatedDate],
MAX(IIF(EventType=1,EventDate,NULL)) [ModifiedDate],
MAX(IIF(EventType=2,EventDate,NULL)) [SubmittedDate],
MAX(IIF(EventType=3,EventDate,NULL)) [ApprovedDate],
MAX(IIF(EventType=0,LastUserID,NULL)) [CreatedBy],
MAX(IIF(EventType=1,LastUserID,NULL)) [ModifiedBy],
MAX(IIF(EventType=2,LastUserID,NULL)) [SubmittedBy],
MAX(IIF(EventType=3,LastUserID,NULL)) [ApprovedBy]
FROM
(
SELECT
DocID,
EventDate,
EventType,
LAST_VALUE(UserID)OVER(
PARTITION BY DocID,EventType
ORDER BY EventDate
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
) LastUserID
FROM #Events
) q
GROUP BY DocID
So I have a table with the following columns:
Type Test Min Max
-----------------------------
1 a 1 2
1 b Null Null
2 a 0 Null
2 b Null 1
Trying to get all of them like this
Type Test1 Test1 min Test1max Test2 Test2min Test2max
------------------------------------------------------------
1 a 1 2 b Null Null
2 a 0 Null b Null 1
Tried using unpivot first before I use pivot but it's still giving duplicate tests and removing null any help with this is much appreciated
Need null values to show up as well
Select type, result
(
From
Select type, min
From table t
)
Unpivot
(result for minmax in (min1)
)
Select
Thanks
using row_number() and conditional aggregation:
select
[Type]
, Test_1 = max(case when rn = 1 then Test end)
, Test_1_Min = max(case when rn = 1 then Min end)
, Test_1_Max = max(case when rn = 1 then Max end)
, Test_2 = max(case when rn = 2 then Test end)
, Test_2_Min = max(case when rn = 2 then Min end)
, Test_2_Max = max(case when rn = 2 then Max end)
from (
select *
, rn = row_number() over (partition by [Type] order by [Test])
from t
) as s
group by s.Type
rextester demo: http://rextester.com/BKL48976
returns:
+------+--------+------------+------------+--------+------------+------------+
| Type | Test_1 | Test_1_Min | Test_1_Max | Test_2 | Test_2_Min | Test_2_Max |
+------+--------+------------+------------+--------+------------+------------+
| 1 | a | 1 | 2 | b | NULL | NULL |
| 2 | a | 0 | NULL | b | NULL | 1 |
+------+--------+------------+------------+--------+------------+------------+
select *
from table t1
join table t2
on t1.type = t2.type
and t1.test < t2.test
I have a table of product stock (ProductStockTemp):
ProductStockId | ProductCode | ProductName | ProductStockClosingBalance
-------------------------------------------------------------------------
1 | A1 | A2 | 200
2 | B1 | B2 | 0
3 | A1 | A2 | 100
4 | C1 | C2 | -400
5 | B1 | B2 | 700
6 | C1 | C2 | 0
7 | D1 | D2 | 0
8 | D1 | D2 | 0
I would like to create a table like that
ProductCode | ProductName | TypeA | TypeB
------------------------------------------
A1 | A2 | 200 | 100
B1 | B2 | 0 | 700
C1 | C2 | -400 | 0
D1 | D2 | 0 | 0
It means the first product record will be the product type A and the latest record will be the product type B. I think i have to select the latest product record first. However, the problem arises when the product appears one time then it will choose this record. In this case, I want the product type B will be 0 since the first will be the product type A and the latest will be the type B. My query to select the latest product record in the table
select
p.ProductCode,
p.ProductName,
p.ProductStockClosingBalance
from
ProductStockTemp p
where
p.ProductStockId = (select MAX(q.ProductStockId)
from ProductStockTemp q
where p.ProductCode = q.ProductCode)
order by
p.ProductCode
I'm really stuck right now!
Most obvius in my opinion for this case:
;with cteStock as
(
select
p.ProductCode,
p.ProductName,
p.ProductStockClosingBalance,
row_number() over(partition by p.ProductCode, p.ProductName order by p.ProductStockId asc) rn_asc,
row_number() over(partition by p.ProductCode, p.ProductName order by p.ProductStockId desc) rn_desc,
from ProductStockTemp p
)
select
s.ProductCode, s.ProductName,
sum(case when s.rn_asc = 1 then s.ProductStockClosingBalance else 0) as TypeA,
sum(case when s.rn_desc = 1 and s.rn_asc != s.rn_desc then s.ProductStockClosingBalance else 0) as TypeB
from cteStock s
group by s.ProductCode, s.ProductName
but it's no good to have such a denormalized table with no info about period and names stored right here.
s.rn_asc != s.rn_desc - for the case when there is only one row.
Not sure about default zero but it's up to you and your task definition.
I suggest you to learn SQL GROUP BY Statement
SELECT ProductCode, ProductName, min(ProductStockClosingBalance) as TypeA, Max(ProductStockClosingBalance) as TypeB
FROM ProductStockTemp p
GROUP BY ProductCode, ProductName
This query does what you want.
declare #prod table(ProductStockId int, ProductCode varchar(10), ProductName varchar(10), ProductStockClosingBalance int)
insert #prod values
( 1 , 'A1' , 'A2' , 200),
( 2 , 'B1' , 'B2' , 0),
( 3 , 'A1' , 'A2' , 100),
( 4 , 'C1' , 'C2' , -400),
( 5 , 'B1' , 'B2' , 700),
( 6 , 'C1' , 'C2' , 0),
( 7 , 'D1' , 'D2' , 0),
( 8 , 'D1' , 'D2' , 0 )
;with prod as(
select *
,ROW_NUMBER() over(partition by productcode order by ProductStockId) rn1
,ROW_NUMBER() over(partition by productcode order by ProductStockId desc) rn2
from #prod
)
select productcode,ProductName,
(select ProductStockClosingBalance from prod p1 where p.productcode=p1.ProductCode and p1.rn1=1) TypeA,
ProductStockClosingBalance typeB
from prod p
where rn2=1
Results:
productcode ProductName TypeA typeB
A1 A2 200 100
B1 B2 0 700
C1 C2 -400 0
D1 D2 0 0
use below query
;With ctef as (select ProductCode , ProductName , ProductStockClosingBalance
row_number()over(partition by ProductCode , ProductName ordered by ProductStockId asc) as r from ProductStock)
, ctef1 as ( select * from ctef where r =1)
, ctel as (select ProductCode , ProductName , ProductStockClosingBalance
row_number()over(partition by ProductCode , ProductName ordered by ProductStockId desc)as r2 from ProductStock )
, ctel1 as ( select * from ctel where r =1)
select f.ProductCode , f.ProductName ,f.ProductStockClosingBalance as typea ,nullif(l.ProductStockClosingBalance ,f.ProductStockClosingBalance ) as typeB
from ctef1 f left join ctel1 s
on f.ProductCode =s.ProductCode and f.ProductName =s.ProductName
if using sql servere 2012 or above Analytic Functions FIRST_VALUE (Transact-SQL) and LAST_VALUE (Transact-SQL) can be used .
Here's the data:
[ TABLE_1 ]
id | prod1 | date1 | prod2 | date2 | prod3 | date3 |
---|--------|--------|--------|--------|--------|-------|
1 | null | null | null | null | null | null |
2 | null | null | null | null | null | null |
3 | null | null | null | null | null | null |
[ TABLE_2 ]
id | date | product |
-----|-------------|-----------|
1 | 20140101 | X |
1 | 20140102 | Y |
1 | 20140103 | Z |
2 | 20141201 | data |
2 | 20141201 | Y |
2 | 20141201 | Z |
3 | 20150101 | data2 |
3 | 20150101 | data3 |
3 | 20160101 | X |
Both tables have other columns not listed here.
date is formatted: yyyymmdd and datatype is int.
[ TABLE_2 ] doesn't have empty rows, just tried to make sample above more readable.
Here's the Goal:
I need to update [ TABLE_1 ] prod1,date1,prod2,date2,prod3,date3
with product collected from [ TABLE_2 ] with corresponding date values.
Data must be sorted so that "latest" product becomes prod1,
2nd latest product will be prod2 and 3rd is prod3.
Latest product = biggest date (int).
If dates are equal, order doesn't matter. (see id=2 and id=3).
Updated [ TABLE_1 ] should be:
id | prod1 | date1 | prod2 | date2 | prod3 | date3 |
---|--------|----------|--------|----------|--------|----------|
1 | Z | 20140103 | Y | 20140102 | X | 20140101 |
2 | data | 20141201 | Y | 20141201 | Z | 20141201 |
3 | X | 20160101 | data2 | 20150101 | data3 | 20150101 |
Ultimate goal is to get the following :
[ TABLE_3 ]
id | order1 | order2 | order3 | + Columns from [ TABLE_1 ]
---|--------------------|----------------------|------------|--------------------------
1 | 20140103:Z | 20140102:Y | 20140103:Z |
2 | 20141201:data:Y:Z | NULL | NULL |
3 | 20160101:X | 20150101:data2:data3 | NULL |
I have to admit this exceeds my knowledge and I haven't tried anything.
Should I do it with JOIN or SELECT subquery?
Should I try to make it in one SQL -clause or perhaps in 3 steps,
each prod&date -pair at the time ?
What about creating [ TABLE_3 ] ?
It has to have columns from [ TABLE_1 ].
Is it easiest to create it from [ TABLE_2 ] -data or Updated [ TABLE_1 ] ?
Any help would be highly appreciated.
Thanks in advance.
I'll post some of my own shots on comments.
After looking into it (after my comment), a stored procedure would be best, that you can call to view the data as a pivot, and do away with TABLE_1. Obviously if you need to make this dynamic, you'll need to look into dynamic pivots, it's a bit of a hack with CTEs:
CREATE PROCEDURE DBO.VIEW_AS_PIVOTED_DATA
AS
;WITH CTE AS (
SELECT ID, [DATE], 'DATE' + CAST(ROW_NUMBER() OVER(PARTITION BY ID ORDER BY [DATE] DESC) AS VARCHAR) AS [RN]
FROM TABLE_2)
, CTE2 AS (
SELECT ID, PRODUCT, 'PROD' + CAST(ROW_NUMBER() OVER(PARTITION BY ID ORDER BY [DATE] DESC) AS VARCHAR) AS [RN]
FROM TABLE_2)
, CTE3 AS (
SELECT ID, [DATE1], [DATE2], [DATE3]
FROM CTE
PIVOT(MAX([DATE]) FOR RN IN ([DATE1],[DATE2],[DATE3])) PIV)
, CTE4 AS (
SELECT ID, [PROD1], [PROD2], [PROD3]
FROM CTE2
PIVOT(MAX(PRODUCT) FOR RN IN ([PROD1],[PROD2],[PROD3])) PIV)
SELECT A.ID, [PROD1], [DATE1], [PROD2], [DATE2], [PROD3], [DATE3]
FROM CTE3 AS A
JOIN CTE4 AS B
ON A.ID=B.ID
Construction:
WITH ranked AS (
SELECT [id]
,[date]
,[product]
,row_number() over (partition by id order by date desc) rn
FROM [sistemy].[dbo].[TABLE_2]
)
SELECT id, [prod1],[date1],[prod2],[date2],[prod3],[date3]
FROM
(
SELECT id, type+cast(rn as varchar(1)) col, value
FROM ranked
CROSS APPLY
(
SELECT 'date', CAST([date] AS varchar(8))
UNION ALL
SELECT 'prod', product
) ca(type, value)
) unpivoted
PIVOT
(
max(value)
for col IN ([prod1],[date1],[prod2],[date2],[prod3],[date3])
) pivoted
You need to take a few steps to achive the aim.
Rank your products by date:
SELECT [id]
,[date]
,[product]
,row_number() over (partition by id order by date desc) rn
FROM [sistemy].[dbo].[TABLE_2]
Unpivot your date and product columns into one column. You can use UNPIVOT OR CROSS APPLY statements. I prefer CROSS APPLY
SELECT id, type+cast(rn as varchar(1)) col, value
FROM ranked
CROSS APPLY
(
SELECT 'date', CAST([date] AS varchar(8))
UNION ALL
SELECT 'prod', product
) ca(type, value)
or the same result using UNPIVOT
SELECT id, type+cast(rn as varchar(1)) col, value
FROM (
SELECT [id],
rn,
CAST([date] AS varchar(500)) date,
CAST([product] AS varchar(500)) prod
FROM ranked) t
UNPIVOT
(
value FOR type IN (date, product)
) unpvt
and at last you use PIVOTE and get a result.