如何透视此表

时间:2012-11-09 08:11:06

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

假设我有以下数据集

+--------------+-----------------------------+------------+-----+-----------+-----------+
| account_name |     PositionDescription     |  FullDate  | Day |  DayName  | ShiftType |
+--------------+-----------------------------+------------+-----+-----------+-----------+
| employee1    | Customer Support Specialist | 2012-11-01 |   1 | Thursday  | G         |
| employee1    | Customer Support Specialist | 2012-11-03 |   3 | Saturday  | G         |
| employee1    | Customer Support Specialist | 2012-11-05 |   5 | Monday    | G         |
| employee1    | Customer Support Specialist | 2012-11-06 |   6 | Tuesday   | G         |
| employee1    | Customer Support Specialist | 2012-11-08 |   8 | Thursday  | G         |
| employee1    | Customer Support Specialist | 2012-11-10 |  10 | Saturday  | G         |
| employee1    | Customer Support Specialist | 2012-11-12 |  12 | Monday    | G         |
| employee1    | Customer Support Specialist | 2012-11-13 |  13 | Tuesday   | G         |
| employee1    | Customer Support Specialist | 2012-11-15 |  15 | Thursday  | G         |
| employee1    | Customer Support Specialist | 2012-11-17 |  17 | Saturday  | G         |
| employee1    | Customer Support Specialist | 2012-11-19 |  19 | Monday    | G         |
| employee1    | Customer Support Specialist | 2012-11-20 |  20 | Tuesday   | G         |
| employee1    | Customer Support Specialist | 2012-11-22 |  22 | Thursday  | G         |
| employee1    | Customer Support Specialist | 2012-11-24 |  24 | Saturday  | G         |
| employee1    | Customer Support Specialist | 2012-11-26 |  26 | Monday    | G         |
| employee1    | Customer Support Specialist | 2012-11-27 |  27 | Tuesday   | G         |
| employee1    | Customer Support Specialist | 2012-11-29 |  29 | Thursday  | G         |
| employee2    | Game Support Specialist     | 2012-11-02 |   2 | Friday    | M         |
| employee2    | Game Support Specialist     | 2012-11-03 |   3 | Saturday  | M         |
| employee2    | Game Support Specialist     | 2012-11-04 |   4 | Sunday    | M         |
| employee2    | Game Support Specialist     | 2012-11-07 |   7 | Wednesday | M         |
| employee2    | Game Support Specialist     | 2012-11-09 |   9 | Friday    | M         |
| employee2    | Game Support Specialist     | 2012-11-10 |  10 | Saturday  | M         |
| employee2    | Game Support Specialist     | 2012-11-11 |  11 | Sunday    | M         |
| employee2    | Game Support Specialist     | 2012-11-14 |  14 | Wednesday | M         |
| employee2    | Game Support Specialist     | 2012-11-16 |  16 | Friday    | M         |
| employee2    | Game Support Specialist     | 2012-11-17 |  17 | Saturday  | M         |
| employee2    | Game Support Specialist     | 2012-11-18 |  18 | Sunday    | M         |
| employee2    | Game Support Specialist     | 2012-11-21 |  21 | Wednesday | M         |
| employee2    | Game Support Specialist     | 2012-11-23 |  23 | Friday    | M         |
| employee2    | Game Support Specialist     | 2012-11-24 |  24 | Saturday  | M         |
| employee2    | Game Support Specialist     | 2012-11-25 |  25 | Sunday    | M         |
| employee2    | Game Support Specialist     | 2012-11-28 |  28 | Wednesday | M         |
| employee2    | Game Support Specialist     | 2012-11-30 |  30 | Friday    | M         |
+--------------+-----------------------------+------------+-----+-----------+-----------+

是否可以将其格式化为此表?

+--------------+-----------------------------+----------------+
| account_name |     PositionDescription     | 1 | 2 | 3 | 4  | and so on...
+--------------+-----------------------------+------------+---+
| employee1    | Customer Support Specialist | G | G | G | G  |
| employee2    | Game Support Specialist     | G | G | G | G  | 
+-----------------------------+------------+-----+------------+

我试图用PIVOT解决它,但我无法得到它。我不知道是否可能:(

假设这是原始查询

SELECT   account_name               
                ,PositionDescription ,FullDate, Day, DayName ,ShiftType         
        FROM ManpowerSchedule ms 

2 个答案:

答案 0 :(得分:2)

我正在添加一个答案,因为另一个在语法中缺少一些东西以使其正常工作。您可以使用PIVOT函数来获取所需的结果。有两种方法可以使用PIVOT静态版本或动态版本。

在静态版本中,您将硬编码需要转换的所有值:

select  * 
from  
( 
  select account_name, PositionDescription, ShiftType, day
  from ManpowerSchedule 
) src
pivot   
( 
  max(ShiftType) 
  FOR day IN ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], .....) 
)  piv;

请参阅SQL Fiddle with Demo

如果您需要转换未知数量的列,则可以使用动态SQL:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX),
    @colsNull AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(day) 
                    from ManpowerSchedule
                    group by day
                    order by day
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

select @colsNull = STUFF((SELECT ', IsNull(' + QUOTENAME(day) +', '''') as '+QUOTENAME(day)
                    from ManpowerSchedule
                    group by day
                    order by day
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT account_name, PositionDescription, ' + @colsNull + ' 
              from 
              (
                select account_name, PositionDescription, ShiftType, day
                from ManpowerSchedule 
              ) x
              pivot 
              (
                max(ShiftType)
                for day in (' + @cols + ')
              ) p '

execute(@query)

请参阅SQL Fiddle with Demo

如果您无权访问PIVOT函数,则可以使用聚合函数和CASE语句复制此函数:

select account_name, 
  PositionDescription,
  max(case when day = 1 then shifttype else '' end) [1],
  max(case when day = 2 then shifttype else '' end) [2],
  max(case when day = 3 then shifttype else '' end) [3],
  max(case when day = 4 then shifttype else '' end) [4],
  max(case when day = 5 then shifttype else '' end) [5],
  max(case when day = 6 then shifttype else '' end) [6],
  max(case when day = 7 then shifttype else '' end) [7],
  max(case when day = 8 then shifttype else '' end) [8],
  max(case when day = 9 then shifttype else '' end) [9],
  max(case when day = 10 then shifttype else '' end) [10]
from ManpowerSchedule
group by account_name, PositionDescription

请参阅SQL Fiddle with Demo

所有三个版本都会给你相同的结果。

答案 1 :(得分:1)

SELECT  * 
FROM    ( select account_name ,PositionDescription  from ManpowerSchedule )
 PIVOT   ( max([ShiftType ]) FOR day IN ([1], [2],......) )  f;