使用动态sql和自定义列名称两次旋转数据

时间:2017-09-12 23:39:43

标签: sql-server sql-server-2008 tsql pivot dynamic-sql

我有一个简单的非唯一帐号,产品ID和数量表:

例如:

UPDATE TABLEB SET MYCOLUMN = 7777 WHERE TABLE_B_KEY = 2;

Error starting at line : 1 in command -
UPDATE TABLEB SET MYCOLUMN = 7777 WHERE TABLE_B_KEY = 2
Error report -
ORA-20819: Direct Modification of MYCOLUMN is forbidden.

我试图将其动态转换为这种结构:

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

将产品ID作为列标题,

with:

account|100|102
1       2.5 6
2       1   NULL

我尝试选择相同的列两次以获取每个列的数量和产品ID,方法是将select语句更改为:

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;

然而,抛出一个错误,''生产被多次指定为'piv'。

将数据转换为两个单独的自定义增量列的最佳方法是什么?

1 个答案:

答案 0 :(得分:2)

无需转轴两次。

示例

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

<强>返回

enter image description here

如果它有助于Visusalization - 子查询产生

enter image description here