使用动态 sql 和自定义列名称旋转数据两次
Pivoting Data twice with dynamic sql and custom column names
我有一个简单的 table non-unique 帐号、产品 ID 和数量:
例如:
account|productid|qty
1 100 1
1 100 1.5
1 102 6
2 100 1
我正在尝试将其动态转换为这种结构:
account|product1|qty1|product2|qty2|etc..|etc..
1 100 2.5 102 6 NULL NULL
2 100 1 NULL NULL NULL NULL
其中一些客户可以订购数百种不同的产品,因此尝试 hard-code 事情最终是不可能的。
我已经设法将其转变为 table 之类的
account|100|102
1 2.5 6
2 1 NULL
产品 ID 作为列 headers,
与:
DECLARE @sql AS NVARCHAR(4000)
, @col AS NVARCHAR(2000);
SELECT @col = ISNULL(@col + ', ', '') + QUOTENAME(x.productid)
FROM
(
SELECT DISTINCT
tp.productid
FROM purchases AS tp
) x
;
SET @sql
= N'SELECT * FROM purchases as p PIVOT ( SUM(qty) FOR [productid] IN (' + @col
+ ')) piv';
SELECT @sql;
EXEC sys.sp_executesql @sql;
我试图 select 相同的列两次以获得每个列的数量和产品 ID,方法是将我的 select 语句更改为:
@coltest = ISNULL(@col + ', ', '') + (QUOTENAME(x.productid) + ', ' + QUOTENAME(x.productid))
然而,抛出错误“为 'piv' 多次指定了 productid。”
将数据透视到两个单独的 custom-named 递增列的最佳方法是什么?
无需旋转两次。
例子
Declare @SQL varchar(max) = '
Select *
From (
Select A.Account
,B.*
From (Select Account
,ProductID
,Qty = sum(Qty)
,RN=Row_Number() over (Partition By Account Order by ProductID)
From YourTable
Group By Account,Productid
) A
Cross Apply (values (''qty''+cast(RN as varchar(25)),cast(Qty as varchar(100)))
,(''product''+cast(RN as varchar(25)),cast(productid as varchar(100)))
) B (Item,Value)
) A
Pivot (max([Value]) For [Item] in (' + Stuff((Select Distinct ','+QuoteName('product'+ColNr)
+','+QuoteName('qty'+ColNr)
From (Select Distinct ColNr=cast(Row_Number() over (Partition By Account,ProductID Order by (Select NULL)) as varchar(25)) From YourTable ) A
Order By 1
For XML Path('')),1,1,'') + ') ) p'
Exec(@SQL);
Print @SQL
Returns
如果它有助于可视化 - 子查询产生
我有一个简单的 table non-unique 帐号、产品 ID 和数量:
例如:
account|productid|qty
1 100 1
1 100 1.5
1 102 6
2 100 1
我正在尝试将其动态转换为这种结构:
account|product1|qty1|product2|qty2|etc..|etc..
1 100 2.5 102 6 NULL NULL
2 100 1 NULL NULL NULL NULL
其中一些客户可以订购数百种不同的产品,因此尝试 hard-code 事情最终是不可能的。
我已经设法将其转变为 table 之类的
account|100|102
1 2.5 6
2 1 NULL
产品 ID 作为列 headers,
与:
DECLARE @sql AS NVARCHAR(4000)
, @col AS NVARCHAR(2000);
SELECT @col = ISNULL(@col + ', ', '') + QUOTENAME(x.productid)
FROM
(
SELECT DISTINCT
tp.productid
FROM purchases AS tp
) x
;
SET @sql
= N'SELECT * FROM purchases as p PIVOT ( SUM(qty) FOR [productid] IN (' + @col
+ ')) piv';
SELECT @sql;
EXEC sys.sp_executesql @sql;
我试图 select 相同的列两次以获得每个列的数量和产品 ID,方法是将我的 select 语句更改为:
@coltest = ISNULL(@col + ', ', '') + (QUOTENAME(x.productid) + ', ' + QUOTENAME(x.productid))
然而,抛出错误“为 'piv' 多次指定了 productid。”
将数据透视到两个单独的 custom-named 递增列的最佳方法是什么?
无需旋转两次。
例子
Declare @SQL varchar(max) = '
Select *
From (
Select A.Account
,B.*
From (Select Account
,ProductID
,Qty = sum(Qty)
,RN=Row_Number() over (Partition By Account Order by ProductID)
From YourTable
Group By Account,Productid
) A
Cross Apply (values (''qty''+cast(RN as varchar(25)),cast(Qty as varchar(100)))
,(''product''+cast(RN as varchar(25)),cast(productid as varchar(100)))
) B (Item,Value)
) A
Pivot (max([Value]) For [Item] in (' + Stuff((Select Distinct ','+QuoteName('product'+ColNr)
+','+QuoteName('qty'+ColNr)
From (Select Distinct ColNr=cast(Row_Number() over (Partition By Account,ProductID Order by (Select NULL)) as varchar(25)) From YourTable ) A
Order By 1
For XML Path('')),1,1,'') + ') ) p'
Exec(@SQL);
Print @SQL
Returns
如果它有助于可视化 - 子查询产生