【问题标题】:SQL Server query : rows make columns (Pivot?)SQL Server 查询:行组成列(枢轴?)
【发布时间】:2011-12-01 08:57:40
【问题描述】:

我有一个问题来查询。

我创建的这个查询

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吗?

【问题讨论】:

  • 从您的帖子中实际上并不太清楚到目前为止您到底尝试了什么。您是否只是试图查找是否有built-in support for pivoting in SQL Server?或者您是否已经尽力掌握如何使用它?还是您已经尝试过该功能本身?请查看此线程的 Related 部分。它包含许多关于在 SQL Server 中进行透视的问题(也有示例)。另一方面,不清楚优先级列的数量是否应该在结果查询中固定。
  • @AndriyM 我在阅读 MSDN 页面后尝试了 Pivot。我达不到。当我尝试 Count 不合适时。我的问题是... DISTINCT(Entry date and Priority) 行进入列,Count 列进入行。对不起我的英语。
  • 所以,我明白了,您在使用 PIVOT 时遇到了困难。我的另一个问题,关于优先级列的问题呢? 输出中是否应该总是正好有四个优先级列,如您的示例(Priorty0Priority1Priority2Priority3)?
  • @AndriyM 是的。优先级的唯一值 0、1、2 或 3。

标签: sql-server-2008 pivot-table


【解决方案1】:

旋转很像分组。您可以将其视为具有“特殊效果”的有限分组。限制在于只能有一个聚合列。 (在普通的 GROUP BY 查询中,自然可以有多个。)当然,“特殊效果”是指其他列之一(同样只有一个)被转换为多个列。

让我们以您的 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 子句中保持不变。

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

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 子句中为透视列取别名,就像任何其他列或表达式一样。因此,最后,您不必以无意义的01 等标识符告终,而是可以为这些列分配您喜欢的任何名称。


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

【讨论】:

  • 非常感谢。我不能用英文表达多少Q.Q
猜你喜欢
  • 2010-12-01
  • 1970-01-01
  • 2015-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多