【问题标题】:SQL Pivot with multiple columns具有多列的 SQL Pivot
【发布时间】:2011-03-15 13:30:03
【问题描述】:

在 sql server 2008 中需要有关 pivot 子句的帮助。 我有一张包含此信息的表格:

Weekno DayOfWeek FromTime ToTime 1 2 10:00 14:00 1 3 10:00 14:00 2 3 08:00 13:00 2 4 09:00 13:00 2 5 14:00 22:00 3 1 06:00 13:00 3 4 06:00 13:00 3 5 14:00 22:00

我想将其转换为如下所示的表格:

周 开始1 结束1 开始2 结束2 开始3 结束3 开始4 结束4 开始5 结束5 开始6 结束6 开始7 结束7 1 10:00 14:00 10:00 14:00 2 08:00 13:00 09:00 13:00 14:00 22:00 3 06:00 13:00 06:00 13:00 14:00 22:00

有什么方法可以处理数据透视查询吗? 请写一个关于如何做到这一点的例子。

感谢您对此提供的任何帮助。提前致谢。

【问题讨论】:

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


【解决方案1】:

这是枢轴版本:

https://data.stackexchange.com/stackoverflow/query/7295/so3241450

-- SO3241450

CREATE TABLE #SO3241450 (
    Weekno int NOT NULL
    ,DayOfWeek int NOT NULL
    ,FromTime time NOT NULL
    ,ToTime time NOT NULL
)

INSERT INTO #SO3241450 VALUES
(1, 2, '10:00', '14:00')
,(1, 3, '10:00', '14:00')
,(2, 3, '08:00', '13:00')
,(2, 4, '09:00', '13:00')
,(2, 5, '14:00', '22:00')
,(3, 1, '06:00', '13:00')
,(3, 4, '06:00', '13:00')
,(3, 5, '14:00', '22:00')

;WITH Base AS (
    SELECT Weekno, DayOfWeek, FromTime AS [Start], ToTime AS [End]
    FROM #SO3241450
)
,norm AS (
SELECT Weekno, ColName + CONVERT(varchar, DayOfWeek) AS ColName, ColValue
FROM Base
UNPIVOT (ColValue FOR ColName IN ([Start], [End])) AS pvt
)
SELECT *
FROM norm
PIVOT (MIN(ColValue) FOR ColName IN ([Start1], [End1], [Start2], [End2], [Start3], [End3], [Start4], [End4], [Start5], [End5], [Start6], [End6], [Start7], [End7])) AS pvt​

【讨论】:

  • 绝对精彩!我现在可以根据需要旋转和显示任意数量的列。谢谢!我要警告这一点,在 UnPivot 过程中(在最后进行 Pivoting 之前)所有列都被放入一个列中。这个例子很好,但如果你混合数字、日期和字符串,我建议将所有内容都转换为 VarChar 以避免错误(然后在需要时转换回它们的原始数据类型)。
【解决方案2】:

我认为 CASE WHEN 只有在只有独特的 Weekno 和 DayofWeek 时才有效,因为它只会返回最新开始和结束时间的记录并过滤掉其余的记录。 示例

Weekno    DayOfWeek     FromTime    ToTime
1         2             10:00       14:00
1         2             07:00       09:00
2         3             08:00       13:00
2         4             09:00       13:00

它只会返回 DayofWeek 2 的第 1 周的第一行并跳过第二行。

【讨论】:

    【解决方案3】:

    我个人讨厌枢轴 - 难以阅读且笨拙。

    CREATE TABLE #test
    (
        WeekNo int,
        [DayOfWeek] int,
        FromTime time,
        ToTime time
        )
    
    INSERT INTO #test
    SELECT 1,2,'10:00','14:00'
    UNION ALL
    SELECT 1,3,'10:00','14:00'
    UNION ALL
    SELECT 2,3,'08:00','13:00'
    UNION ALL
    SELECT 2,4,'09:00','13:00'
    UNION ALL
    SELECT 2,5,'14:00','22:00'
    UNION ALL
    SELECT 3,1,'06:00','13:00'
    UNION ALL
    SELECT 3,4,'06:00','13:00'
    UNION ALL
    SELECT 3,5,'14:00','22:00'
    
    SELECT WeekNo, 
        MAX(CASE WHEN DayOfWeek = 1 THEN FromTime ELSE NULL END)  AS Start1,
        MAX(CASE WHEN DayOfWeek = 1 THEN ToTime ELSE NULL END)  AS End1,
        MAX(CASE WHEN DayOfWeek = 2 THEN FromTime ELSE NULL END)  AS Start2,
        MAX(CASE WHEN DayOfWeek = 2 THEN ToTime ELSE NULL END)  AS End2,
        MAX(CASE WHEN DayOfWeek = 3 THEN FromTime ELSE NULL END)  AS Start3,
        MAX(CASE WHEN DayOfWeek = 3 THEN ToTime ELSE NULL END)  AS End3,
        MAX(CASE WHEN DayOfWeek = 4 THEN FromTime ELSE NULL END)  AS Start4,
        MAX(CASE WHEN DayOfWeek = 4 THEN ToTime ELSE NULL END)  AS End4,
        MAX(CASE WHEN DayOfWeek = 5 THEN FromTime ELSE NULL END)  AS Start5,
        MAX(CASE WHEN DayOfWeek = 5 THEN ToTime ELSE NULL END)  AS End5,
        MAX(CASE WHEN DayOfWeek = 6 THEN FromTime ELSE NULL END)  AS Start6,
        MAX(CASE WHEN DayOfWeek = 6 THEN ToTime ELSE NULL END)  AS End6,
        MAX(CASE WHEN DayOfWeek = 7 THEN FromTime ELSE NULL END)  AS Start7,
        MAX(CASE WHEN DayOfWeek = 7 THEN ToTime ELSE NULL END)  AS End7
        FROM #test
        GROUP BY WeekNo
    

    它会把袜子从枢轴上吹下来;性能方面。

    【讨论】:

    • 看起来这两种方法在性能方面是平局。
    • @Martin Smith - 我的必须先 UNPIVOT。正因为如此,我原以为传统的“枢轴”会更快。
    • 根据这个数据集真的无法判断;需要创建一些大型测试数据。即使有这么小的数据,交叉表的性能也更好(0ms vs 6ms)。但如果您对差异感兴趣,请查看执行计划。
    • 我现在无法访问 SQL,但我相当肯定有几百万行我们可以看到很好的差异。如果我不能吹掉你的袜子,我会吃掉它们! :)
    • @Mike - 是的,对不起。我刚刚尝试了 50 万行,你是绝对正确的,其中几个额外的运算符开始变得重要,并且 CPU 时间达到了顶峰。
    猜你喜欢
    • 1970-01-01
    • 2012-10-15
    • 1970-01-01
    • 2017-04-04
    • 1970-01-01
    • 2018-06-28
    • 2012-03-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多