简单的数据透视表与月和文本数据动态SQL

时间:2015-06-21 01:28:49

标签: sql sql-server tsql pivot

如何使用以下数据在Dynamic SQL中创建简单的数据透视表:

 ID Month   AssignmentMonth Designation
 1  5            May         Joe Blow
 2  5            May         Available
 3  5            May         Available
 4  5            May         Available
 5  6            June        Carry over
 6  6            June        Christopher Freeberg
 7  6            June        Ringo Starr
 8  6            June        Robert L Testcustomer
 9  7            July        Carry over
10  7            July        Carry over
11  7            July        Carry over
12  7            July        Carry over
13  8            August      Available
14  8            August      Carry over
15  8            August      Carry over
16  8            August      Carry over

所以当它完成时它看起来像下面的例子:

May               June                 July                 August

Joe Blow         Carry Over            Carry over          Available
Available        Christopher Freeburg  Carry over          Carry over
Available        Ringo Starr           Carry over          Carry over
Available        Robert L Testcustomer Carry over          Carry over

这是我的尝试,但它确实产生了正确的结果。它只返回一行。

   August        July       June                    May
   Carry over   Carry over  Robert L Testcustomer   Joe Blow

    DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

    select @cols = STUFF((SELECT distinct ',' +   QUOTENAME(AssignmentMonth) 
                from @CardAssigns
        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'') 
SET @query = 'WITH PivotData AS
(
SELECT   Designation, AssignmentMonth      
FROM    #Temp1
)
SELECT  '+ @cols +'
FROM PivotData
PIVOT
(
MAX(Designation)
FOR AssignmentMonth
IN ( '+ @cols +' )
) as PIVOTResult'

EXECUTE(@query)

2 个答案:

答案 0 :(得分:1)

您的查询存在的问题是,透视查询没有要分组的列。 pivot表运算符会自动GROUP BY来自锚点查询的部分MAX(Designation) FOR AssignmentMonth IN ...中未列出的列,因此在您的查询中,您只有两列来自锚定查询DesignationAssignmentMonth,因此您的查询没有任何额外的列可以分组,以便它为您提供只有一行的MAX(Designation)。但是,您可以通过再添加一列来进行解决方法,因为您无法按IDMonth进行分组,您可以添加行号列,它将会给你想要的结果,如下:

SET @query = 'WITH PivotData AS
(
  SELECT   
    Designation, 
    AssignmentMonth, 
    ROW_NUMBER() OVER(PARTITION BY   AssignmentMonth ORDER BY ID) AS RN
  FROM   CardAssigns
)
SELECT  '+ @cols +'
FROM PivotData
PIVOT
(
  MAX(Designation)
  FOR AssignmentMonth
  IN ( '+ @cols +' )
) as PIVOTResult';

EXECUTE(@query);

这会给你:

|     August |       July |                  June |       May |
|------------|------------|-----------------------|-----------|
|  Available | Carry over |            Carry over |  Joe Blow |
| Carry over | Carry over |  Christopher Freeberg | Available |
| Carry over | Carry over |           Ringo Starr | Available |
| Carry over | Carry over | Robert L Testcustomer | Available |

答案 1 :(得分:0)

下面的示例使用动态查询和ROW_NUMBER来排列您所描述的值。

CREATE TABLE #Data (
    ID INT,
    Month INT,
     AssignmentMonth VARCHAR(50),
     Designation VARCHAR(50)

)
INSERT #Data VALUES
(1,5,'May','Joe Blow'),
(2,5,'May','Available'),
(3,5,'May','Available'),
(4,5,'May','Available'),
(5,6,'June','Carry over'),
(6,6,'June','Christopher Freeberg'),
(7,6,'June','Ringo Starr'),
(8,6,'June','Robert L Testcustomer'),
(9,7,'July','Carry over'),
(10,7,'July','Carry over'),
(11,7,'July','Carry over'),
(12,7,'July','Carry over'),
(13,8,'August','Available'),
(14,8,'August','Carry over'),
(15,8,'August','Carry over'),
(16,8,'August','Carry over')

DECLARE @ColumnList VARCHAR(MAX) =
    SUBSTRING((
        SELECT
            ',[' + AssignmentMonth + ']' AS [text()]
        FROM #Data
        GROUP BY AssignmentMonth
        ORDER BY MIN(ID)
        FOR XML PATH('')
    ), 2, 4000)
DECLARE @ColumnAggs VARCHAR(MAX) =
    SUBSTRING((
        SELECT
            ',MAX([' + AssignmentMonth + ']) AS [' + AssignmentMonth + ']' AS [text()]
        FROM #Data
        GROUP BY AssignmentMonth
        ORDER BY MIN(ID)
        FOR XML PATH('')
    ), 2, 4000)

DECLARE @Sql VARCHAR(MAX) =
    'SELECT ' + @ColumnAggs + ' FROM ('
    + 'SELECT ROW_NUMBER() OVER (PARTITION BY Month ORDER BY ID) AS RowId, ' + @ColumnList
    + 'FROM #Data D PIVOT (MAX(Designation) FOR AssignmentMonth IN (' + @ColumnList + ')) P'
    + ') T GROUP BY RowId'
    PRINT @Sql
EXEC (@Sql)

输出

May                            June                           July                           August
------------------------------ ------------------------------ ------------------------------ ------------------------------
Joe Blow                       Carry over                     Carry over                     Available
Available                      Christopher Freeberg           Carry over                     Carry over
Available                      Ringo Starr                    Carry over                     Carry over
Available                      Robert L Testcustomer          Carry over                     Carry over