sql server pivot查询 - 需要帮助

时间:2017-02-13 21:52:41

标签: sql sql-server pivot

我需要编写SQL server查询来从源表中转移数据。

我的源表看起来像这样 -

Cust_Id  Item1_Desc_Count   Item2_Desc_Count   Item3_Desc_Count
-------  ----------------   ----------------   ------------
Cust1    10                 12                 9
Cust2    7                  1                  3
Cust3    12                 6                  0
...

项目主表格如下所示 -

Item_Id Item_Desc
------- ---------
1       Item1_Desc
2       Item2_Desc
3       Item3_Desc 

请注意,项目描述用于源表中的列名。

我需要输出 -

Cust_Id   Item_Id   Count
--------  --------- ------
Cust1     1         10
Cust1     2         12
Cust1     3         9
Cust2     1         7
Cust2     2         1
Cust2     3         3
Cust3     1         12
... 

任何人都可以帮我用SQL查询来实现这个目标吗?

2 个答案:

答案 0 :(得分:2)

这是一种更具活力的方法。无需指定所有项目计数列。

CROSS APPLY UNPIVOT 来源表。

我应该添加UNPIVOT会更高效,但我假设你有很多计数列。

创建示例数据

Declare @Source table (Cust_Id varchar(25),Item1_Desc_Count int,Item2_Desc_Count int,Item3_Desc_Count int)
Insert Into @Source values
('Cust1',10,12,9),
('Cust2', 7, 1,3),
('Cust3',12, 6,0)

Declare @Item table (Item_Id int,Item_Desc varchar(50))
Insert Into @Item values
(1,'Item1_Desc'),
(2,'Item2_Desc'),
(3,'Item3_Desc')

代码示例

Select B.Cust_ID
      ,C.Item_ID
      ,Count = B.Value
 From  (Select XMLData = cast((Select * From @Source for XML Raw) as XML)) A
 Cross Apply (
                Select Cust_ID = r.value('@Cust_Id','varchar(50)')
                      ,Item    = attr.value('local-name(.)','varchar(100)')
                      ,Value   = attr.value('.','varchar(max)') 
                 From  A.XMLData.nodes('/row') as A(r)
                 Cross Apply A.r.nodes('./@*') AS B(attr)
                 Where attr.value('local-name(.)','varchar(100)') not in ('Cust_ID','OtherFieldsToExclude')
             ) B
 Join @Item C on B.Item Like C.Item_Desc+'%'

<强>返回

Cust_ID Item_ID Count
Cust1   1       10
Cust1   2       12
Cust1   3       9
Cust2   1       7
Cust2   2       1
Cust2   3       3
Cust3   1       12
Cust3   2       6
Cust3   3       0

编辑 - UnPivot选项

Select A.Cust_ID
      ,B.Item_ID
      ,Count = A.Value
 From (
        Select Cust_Id,Item,value
        From @Source 
        Unpivot ( Value for Item in (Item1_Desc_Count,Item2_Desc_Count,Item3_Desc_Count) ) u 
       ) A
Join @Item B on A.Item Like B.Item_Desc+'%'

答案 1 :(得分:0)

如果我理解,您希望将源表列名称与主表的内容联系起来。

枢轴不能以这种方式工作。当您想要转换数据时,就像

一样

Cust1 10 7 12 Cust2 12 1 6 Cust3 9 3 0

(查看此示例:https://blogs.msdn.microsoft.com/spike/2009/03/03/pivot-tables-in-sql-server-a-simple-sample/

在这种情况下,我看到了这个解决方案(但Item_ID将被硬编码):

select Cust_Id, 1, Item1_Desc_Count as count FROM SourceTable UNION ALL select Cust_Id, 2, Item2_Desc_Count as count FROM SourceTable UNON ALL ...etc

我同意它不是很优雅,但如果源表列名与主表中的item_descs之间没有完美匹配,那么它很简单灵活