如何 select 数据行转换为列 w/out 知道所有值

How to select data rows into columns w/out knowing all values

下面是 table 我有一些订单的详细信息。

OrderID TypeID Amount
11148   1      900
11148   7      30
11148   6      75
12506   3      100
12506   4      60
16845   1      30

是否可以return像这样:

OrderID TypeID1 Amount1 TypeID2 Amount2 TypeID3 Amount3
11148   1       900     7       30      6       75    
12506   3       100     4       60      null    null
16845   1       30      null    null    null    null

我想得到这样的结果,这样我就可以将其他订单信息加入到另一个结果集中,但每个 ID 只能有一行。我一直在尝试使用 Pivot,但似乎我需要知道 TYPEID 的所有可能结果,并且有那么多列,而不仅仅是我正在寻找的 3 个 TYPEID 和 3 个 AMOUNT。

下面是 Pivot table 我知道如何开始工作,但这不是我们想要的,因为这样我就有了每种 ID 类型的列,但我更希望它们也位于行中。

SELECT OrderID
    ,[1] as Amount1
    ,[2] as Amount2
    ,[3] as Amount3
    ,[4] as Amount4
    ,[5] as Amount5
    ,[6] as Amount6
    ,[7] as Amount7
FROM ( 
    SELECT ORDERID, TYPEID, AMOUNT
    FROM Order_Details
)x
PIVOT
(
    MAX(AMOUNT)
    FOR TYPEID in ([1],[2],[3],[4],[5],[6],[7])
)P

OrderID Amount1 Amount2 Amount3 Amount4 Amount5 Amount6 Amount7
11148   900     null    null    null    null    75      30   
12506   null    null    100     60      null    null    null
16845   30      null    null    null    null    null    null

解决方案是将自外部连接与 row_number 分区相结合,例如:

select t1.OrderId as OrderID1, t1.TypeID as TypeID1, t1.Amount as Amount1,
t2.TypeID as TypeID2, t2.Amount as Amount2,
t3.TypeID as TypeID3, t3.Amount as Amount3 from 
(
SELECT OrderID, TypeID, Amount 
FROM (
select OrderID , TypeID, Amount ,ROW_NUMBER() OVER (PARTITION BY OrderID order by OrderID) AS RN
from tt
)Sub
WHERE rn = 1) t1 left join
(
SELECT OrderID, TypeID, Amount 
FROM (
select OrderID , TypeID, Amount ,ROW_NUMBER() OVER (PARTITION BY OrderID order by OrderID) AS RN
from tt
)Sub
WHERE rn = 2) t2 on t1.OrderID=t2.OrderID left join
(
SELECT OrderID, TypeID, Amount
FROM (
select OrderID , TypeID, Amount ,ROW_NUMBER() OVER (PARTITION BY OrderID order by OrderID) AS RN
from tt
)Sub
WHERE rn = 3) t3 on t1.OrderID=t3.OrderID; 

live example

通过使用交叉应用和 Row_number 我们可以获得相同的结果

declare @Table1 TABLE 
    (OrderID int, TypeID int, Amount int)
;

INSERT INTO @Table1
    (OrderID, TypeID, Amount)
VALUES
    (11148, 1, 900),
    (11148, 7, 30),
    (11148, 6, 75),
    (12506, 3, 100),
    (12506, 4, 60),
    (16845, 1, 30)
;



;with CTE As (
 select OrderID,[TypeID1],[TypeID2],[TypeID3] from (
 Select OrderID,
 val,
 COL + CAST(ROW_NUMBER()OVER(PARTITION BY OrderID ORDER BY OrderID) AS VARCHAR(1))RN  
    FROM @Table1 
CROSS APPLY (VALUES ('TypeID',TypeID))CS(Col,val))T
PIVOT (MAX(VAL) FOR RN IN ([TypeID1],[TypeID2],[TypeID3]))P )
,CTE2 AS (select OrderID,[Amount1],[Amount2],[Amount3] from (
 Select OrderID,
 val,
 COL + CAST(ROW_NUMBER()OVER(PARTITION BY OrderID ORDER BY OrderID) AS VARCHAR(1))RN  
    FROM @Table1 
CROSS APPLY (VALUES ('Amount',Amount))CS(Col,val))T
PIVOT (MAX(VAL) FOR RN IN ([Amount1],[Amount2],[Amount3]))P)

select c.OrderID,c.TypeID1,cc.Amount1,c.TypeID2,cc.Amount2,c.TypeID3,cc.Amount3 from CTE C
LEFT JOIN CTE2 CC
ON c.OrderID = cc.OrderID