具有多列的SQL Pivot

具有多列的SQL Pivot,sql,sql-server,sql-server-2008,pivot,Sql,Sql Server,Sql Server 2008,Pivot,需要有关sql server 2008中pivot子句的帮助。 我有一张包含以下信息的表格: 每周的第二天 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:

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

每周的第二天 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结束3开始4结束4开始5结束5开始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

有什么方法可以处理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
它会把枢轴上的袜子吹走;性能方面。

以下是pivot版本:


我认为只有在只有唯一的Weekno和DayofWeek的情况下,WHEN才会起作用,因为它只会返回最新开始和结束时间的记录,并过滤掉其余的记录。 范例


它将只返回第1周的第一行,即第2周的第2天,并跳过第二行。

从性能角度看,这两种方法之间似乎是一种平局。@Martin Smith-Mine必须先取消Pivot。正因为如此,我本以为传统的“支点”会更快;需要创建一些大型测试数据。即使有这么小的数据,交叉表的性能也更好(0毫秒比6毫秒)。但是,如果您对差异感兴趣,请查看执行计划。我现在无法访问SQL,但我相当确定,对于数百万行,我们可以看到一个很好的差异。如果我不能把你的袜子脱掉,我就把它们吃掉!:)@迈克:是的,对不起。我刚刚尝试了50万行,你完全正确,其中一些额外的操作符开始变得重要,CPU时间达到了顶点。绝对精彩!我现在可以旋转并显示任意数量的列。非常感谢。我想警告一下,在UnPivot过程中(在最后旋转之前),所有列都被抛出到一个列中。对于本例来说,这很好,但如果您混合使用数字、日期和字符串,我建议将所有内容转换为VarChar以避免错误(然后在需要时转换回其原始数据类型) Week Start1 End1 Start2 End2 Start3 End3 Start4 End4 Start5 End5 Start6 End6 Start7 End7 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
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
-- 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​
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