在SQL Server中的多个列上使用Pivot

时间:2016-02-01 09:31:14

标签: sql-server pivot

我有一个日历事件表,其中包含以下架构:

CREATE TABLE [dbo].[Calendar](
    [ID] [int] NOT NULL,
    [PersonCode] [int] NOT NULL,
    [Title] [nvarchar](50) NULL,
    [Description] [nvarchar](max) NULL,
    [StartDate] [datetime] NULL,
    [EndDate] [datetime] NULL,
    [NotifyOrder] [int] NULL)

 INSERT INTO [dbo].[Calendar]
       ([ID]
       ,[PersonCode]
       ,[Title]
       ,[Description]
       ,[StartDate]
       ,[EndDate]
       ,[NotifyOrder])
 VALUES
       (1
       ,1000
       ,'Calendar Event 1'
       ,'Description For Event 1'
       ,'2016/01/28 08:00'
       ,'2016/01/28 09:00'
       ,1)


INSERT INTO [dbo].[Calendar]
       ([ID]
       ,[PersonCode]
       ,[Title]
       ,[Description]
       ,[StartDate]
       ,[EndDate]
       ,[NotifyOrder])    
 VALUES
       (2
       ,1000
       ,'Calendar Event 2'
       ,'Description For Event 2'
       ,'2016/01/28 09:00'
       ,'2016/01/28 10:00'
       ,2)

INSERT INTO [dbo].[Calendar]
       ([ID]
       ,[PersonCode]
       ,[Title]
       ,[Description]
       ,[StartDate]
       ,[EndDate]
       ,[NotifyOrder])    
 VALUES
       (3
       ,1000
       ,'Calendar Event 3'
       ,'Description For Event 3'
       ,'2016/01/28 10:00'
       ,'2016/01/28 11:00'
       ,3)

我需要以这样的格式显示行:

 EventDate  |    1      |   Title1          |     2     |   Title2          |     3     |   Title3         |
 -----------------------------------------------------------------------------------------------------------
  2016-01-28|08:00-09:00 | Calendar Event 1 |09:00-10:00| Calendar Event 2  |10:00-11:00| Calendar Event 3 |

当我仅在行号列(这里是NotifyOrder)上使用数据透视表时,outpu是正确的(没有标题列):

SELECT   EventDate
, [1], [2], [3], [4], [5], [6]
FROM 
(
 SELECT  NotifyOrder 
    ,CAST(StartDate AS Date) EventDate
    ,FORMAT(StartDate ,'hh:mm')  + ' - ' + FORMAT(EndDate ,'hh:mm')  EventTime 
 FROM [Calendar] 
 ) Notifies

 PIVOT 
(
    Max(EventTime) for NotifyOrder IN([1], [2], [3], [4], [5], [6])
) AS PV1

结果是:

 EventDate      1           |   2               |   3               |   4   |   5       |   6
-----------------------------------------------------------------------------------------------
2016-01-28  08:00 - 09:00   |   09:00 - 10:00   |   10:00 - 11:00   | NULL  |   NULL    |   NULL

但是当我在Title Columns上添加Pivot时,结果会以多行显示:

    SELECT   EventDate
        , [1], [2], [3], [4], [5], [6]
        , [Title1], [Title2], [Title3], [Title4], [Title5], [Title6] 
    FROM 
    (
     SELECT  NotifyOrder 
            ,CAST(StartDate AS Date) EventDate
  ,FORMAT(StartDate ,'hh:mm')  + ' - ' + FORMAT(EndDate ,'hh:mm')  EventTime                ,Title, 'Title' + CAST(NotifyOrder AS Varchar(2)) AS EventTitle
     FROM [Calendar] 
     ) Notifies

     PIVOT 
    (
        Max(EventTime) for NotifyOrder IN([1], [2], [3], [4], [5], [6])
    ) AS PV1

     PIVOT 
     (
        MAX (Title) for EventTitle IN([Title1], [Title2], [Title3], [Title4], [Title5], [Title6])
     ) AS PV2

EventDate   1   2   3   4   5   6   Title1  Title2  Title3  Title4  Title5  Title6
2016-01-28  (null)  (null)  10:00 - 11:00   (null)  (null)  (null)  (null)  (null)  Calendar Event 3    (null)  (null)  (null)
2016-01-28  (null)  09:00 - 10:00   (null)  (null)  (null)  (null)  (null)  Calendar Event 2    (null)  (null)  (null)  (null)
2016-01-28  08:00 - 09:00   (null)  (null)  (null)  (null)  (null)  Calendar Event 1    (null)  (null)  (null)  (null)  (null)

这是SQL小提琴源:

http://sqlfiddle.com/#!6/a34a5/1

1 个答案:

答案 0 :(得分:4)

使用条件聚合和FORMAT

SELECT PersonCode
 ,[1]      = MAX(CASE WHEN rn = 1 THEN EventTime END)
 ,[Title1] = MAX(CASE WHEN rn = 1 THEN Title END)
 ,[2]      = MAX(CASE WHEN rn = 2 THEN EventTime END)
 ,[Title2] = MAX(CASE WHEN rn = 2 THEN Title END)
 ,[3]      = MAX(CASE WHEN rn = 3 THEN EventTime END)
 ,[Title3] = MAX(CASE WHEN rn = 3 THEN Title END)
FROM (SELECT *, rn = ROW_NUMBER() OVER(PARTITION BY PersonCode ORDER BY id)
          ,EventTime = FORMAT(StartDate, 'hh:mm') + '-' + FORMAT(EndDate, 'hh:mm')
      FROM #Calendar) AS sub
GROUP BY PersonCode; 

LiveDemo

输出:

╔════════════╦═════════════╦══════════════════╦═════════════╦══════════════════╦═════════════╦══════════════════╗
║ PersonCode ║      1      ║      Title1      ║      2      ║      Title2      ║      3      ║      Title3      ║
╠════════════╬═════════════╬══════════════════╬═════════════╬══════════════════╬═════════════╬══════════════════╣
║       1000 ║ 08:00-09:00 ║ Calendar Event 1 ║ 09:00-10:00 ║ Calendar Event 2 ║ 10:00-11:00 ║ Calendar Event 3 ║
╚════════════╩═════════════╩══════════════════╩═════════════╩══════════════════╩═════════════╩══════════════════╝

如果您使用的SQL Server低于2012,请将FORMAT更改为您的自定义代码。