如何根据 sql 中的订单 ID 生成列

How to generate column based on order id in sql

我有两个 table:customerTableorderTable,如下所示。我需要动态生成 order 列。

客户表

custId CustName
01     Suresh
02     Ramesh

订单表

custId  OrderId 
01      011
01      012

需要像这样的输出:

custId Order1 Order2
01     011    012

此处如果每个客户的订单多次,则将动态添加列。

如果 custId = 01 有 011,012,013,014 ...... 有很多订单那么 table 就像

custId order1  order2 order3 order4 order5 order6 ...... many oder N columns 
01     011       012   013   014    015    06     ....... 0N..   

您要查找的内容称为旋转。见 documentation.

取自上面 link 的一个简单示例:

USE AdventureWorks2008R2;
GO
SELECT
    DaysToManufacture,
    AVG(StandardCost) AS AverageCost
FROM Production.Product
GROUP BY DaysToManufacture;

结果:

DaysToManufacture | AverageCost
----------------------------------------
0                 | 5.0885
1                 | 223.88
2                 | 359.1082
4                 | 949.4105

这些是源中 table 分组的行,尚未完成旋转。通过旋转,您将第 1 列中的行的值转换为列,而第 2 列中的行的值得到 'rotated' 并显示为一行。 SQL 执行以下操作:

-- Pivot table with one row and five columns
SELECT
    'AverageCost' AS Cost_Sorted_By_Production_Days, 
    [0],
    [1],
    [2],
    [3],
    [4]
FROM
(
    SELECT
        DaysToManufacture,
        StandardCost 
    FROM
        Production.Product
) AS SourceTable
PIVOT
(
    AVG(StandardCost)
    FOR DaysToManufacture IN
    (
        [0],
        [1],
        [2],
        [3],
        [4]
    )
) AS PivotTable;

这导致输出如:

Cost_Sorted_By_Production_Days | 0      | 1      | 2        | 3    | 4
-----------------------------------------------------------------------------
AverageCost                    | 5.0885 | 223.88 | 359.1082 | NULL | 949.4105

像这样动态地执行此操作:

declare @sql as nvarchar(max)
declare @cols as nvarchar(max)

set @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.OrderId)
            FROM OrderTable c
            order by 1
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'');

set @sql = STUFF((SELECT ',' + QUOTENAME(OrderId) + ' as Order' + convert(varchar,row_number() over (order by OrderId))
            from (
                select distinct OrderId 
                FROM OrderTable
            ) t
            order by 1
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'');

set @sql = 'SELECT custId, ' + @sql + ' from 
            (
                select *
                from OrderTable
           ) x
            pivot 
            (
                 max(OrderId)
                for OrderId in (' + @cols + ')
            ) p '
exec(@sql)

产生:

这里要注意的是,它对一个 custId 有效,因为列是根据旋转结果中的 OrderId 对齐的。