SQL Server查询:行创建列(Pivot?)

时间:2011-12-01 08:57:41

标签: sql-server-2008 pivot-table

我有一个问题要提出疑问。

我创建的这个查询

WITH TATH(Priority, EntryDate) AS 
(
    SELECT TH.Priority as Priority, DATEADD(dd, 0, DATEDIFF(dd, 0, entryDate)) as EntryDate  
      FROM TicketAssignment TA, TicketHeader TH 
     WHERE TA.TicketID = TH.TicketID   
       AND TA.Company = 'IT'
       AND TA.CurrentRole IN ('SA1B','SA1C','SDA')
) 
SELECT Priority, convert(varchar(10), EntryDate,103) as EntryDate, COUNT(*) AS Count  
FROM TATH 
GROUP BY Priority, EntryDate 

到目前为止的结果是:

Priority    EntryDate   Count
0   25/11/2011  1
1   25/11/2011  2
2   25/11/2011  36
3   25/11/2011  8
0   28/11/2011  3
1   28/11/2011  3
2   28/11/2011  37
3   28/11/2011  37

我想让结果看起来像这样

EntryDate   Priorty0    Priority1   Priority2   Priority3
25/11/2011  1   2   36  8
28/11/2011  3   3   37  37

我认为这是我的能力,但我无法实现它。

如果一个支点不是一个好的解决方案,我必须搜索(或研究)?

你能帮帮我Q.Q吗?

1 个答案:

答案 0 :(得分:2)

透视与分组非常相似。您可以将其视为具有“特殊效果”的有限分组。限制在于事实上只能有一个聚合列。 (在正常的GROUP BY查询中,你可以自然地拥有多个。)而且,通过'特殊效果',我的意思是,其他列中的一个(以及同样只有一个)被转换为多个列。 / p>

我们以您的GROUP BY查询为例。输出中有三列。其中之一Count是包含聚合信息的列。这是分散在PIVOT查询中的多个列中的那个。另一列Priority是结果分组的另外两列之一,也是需要转动的列。最后,EntryDate是另一个GROUP BY列。它应该保持原样,因为它不直接参与旋转。

现在让我们看看你的主要SELECT如何从常规的GROUP BY查询转换为PIVOT查询,一步一步:

  1. 由于PIVOT查询中隐含了分组,因此将删除GROUP BY子句。相反,引入了PIVOT条款。

  2. Count列的表达式从SELECT子句移到PIVOT子句。

  3. Priority列的拆分在PIVOT子句中定义。

  4. SELECT子句中的PriorityCount列将替换为PIVOT子句中定义的列的列表。

  5. EntryDate列在SELECT子句中保持不变。

  6. 这是结果查询,注释标记了上述转换的每个部分:

    WITH TATH(Priority, EntryDate) AS 
    (
        SELECT TH.Priority as Priority, DATEADD(dd, 0, DATEDIFF(dd, 0, entryDate)) as EntryDate
          FROM TicketAssignment TA, TicketHeader TH 
         WHERE TA.TicketID = TH.TicketID   
           AND TA.Company = 'IT'
           AND TA.CurrentRole IN ('SA1B','SA1C','SDA')
    ) 
    SELECT
      convert(varchar(10), EntryDate,103) as EntryDate,                       -- #5
      [0] AS Priority0, [1] AS Priority1, [2] AS Priority2, [3] AS Priority3  -- #4
    FROM TATH
    PIVOT (                                                                   -- #1
      COUNT(*)                                                                -- #2
      FOR Priority IN ([0], [1], [2], [3])                                    -- #3
    ) p
    
    /*  -- your original main query, for comparison
    SELECT
      Priority,                                                               -- #4
      convert(varchar(10),                                                    -- #5
      EntryDate,103) as EntryDate, COUNT(*) AS Count                          -- ##2&4
    FROM TATH 
    GROUP BY Priority, EntryDate                                              -- #1
    */
    

    PIVOT子句中的列列表还有一个注释。首先,您必须了解,根据列数及其名称,生成的SQL查询集应该是固定的 * 。这意味着您必须显式枚举要在输出中看到的所有转换列。名称是从被旋转的列的值派生而来的,但它们应指定为 names ,而不是值。这就是为什么你可以在列出的数字周围看到方括号。由于数字本身不满足rules for regular identifiers,因此必须将它们分隔开来。

    您还可以看到,您可以像SELECT任何其他列或表达式一样为SELECT子句中的透视列添加别名。因此,最后,您不必最终使用无意义的01等标识符,而是可以为这些列分配您喜欢的任何名称。


    * 如果您希望透视列的数量和/或名称是动态的,则必须动态构建查询,即首先收集名称,然后将它们合并到包含查询其余部分的字符串中,并使用EXEC ()EXEC sp_executesql调用最终查询。您可以search this site获取有关动态旋转的更多信息。