如何根据 sql 中的订单 ID 生成列
How to generate column based on order id in sql
我有两个 table:customerTable
和 orderTable
,如下所示。我需要动态生成 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 对齐的。
我有两个 table:customerTable
和 orderTable
,如下所示。我需要动态生成 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 对齐的。