如何将行转移到列中(自定义透视)

时间:2010-06-25 19:25:23

标签: sql tsql pivot

我有一个类似于以下内容的Sql Database表:

Day   Period    Subject

Mon   1         Ch
Mon   2         Ph
Mon   3         Mth
Mon   4         CS
Mon   5         Lab1
Mon   6         Lab2
Mon   7         Lab3
Tue   1         Ph
Tue   2         Ele
Tue   3         Hu
Tue   4         Ph
Tue   5         En
Tue   6         CS2
Tue   7         Mth

我希望它显示如下:交叉表或Pivot的种类

Day   P1   P2   P3   P4   P5   P6   P7

Mon   Ch   Ph   Mth  CS2  Lab1 Lab2 Lab3
Tue   Ph   Ele  Hu   Ph   En   CS2  Mth

理想的做法是什么?有人可以请给我看一下Sql代码吗?

6 个答案:

答案 0 :(得分:18)

你可以用PIVOT功能做到这一点,但我更喜欢老派的方法:

SELECT
    dy,
    MAX(CASE WHEN period = 1 THEN subj ELSE NULL END) AS P1,
    MAX(CASE WHEN period = 2 THEN subj ELSE NULL END) AS P2,
    MAX(CASE WHEN period = 3 THEN subj ELSE NULL END) AS P3,
    MAX(CASE WHEN period = 4 THEN subj ELSE NULL END) AS P4,
    MAX(CASE WHEN period = 5 THEN subj ELSE NULL END) AS P5,
    MAX(CASE WHEN period = 6 THEN subj ELSE NULL END) AS P6,
    MAX(CASE WHEN period = 7 THEN subj ELSE NULL END) AS P7
FROM
    Classes
GROUP BY
    dy
ORDER BY
    CASE dy
        WHEN 'Mon' THEN 1
        WHEN 'Tue' THEN 2
        WHEN 'Wed' THEN 3
        WHEN 'Thu' THEN 4
        WHEN 'Fri' THEN 5
        WHEN 'Sat' THEN 6
        WHEN 'Sun' THEN 7
        ELSE 8
    END
  • 我更改了一些列名以避免使用保留字

答案 1 :(得分:12)

只是想要你想要新的学校方法。 (Pivot语句应该在SQL2005 +中工作,VALUES位仅用于示例数据SQL2008)

WITH ExampleData AS
(
SELECT X.*
  FROM (VALUES  
('Mon', 1, 'Ch'),
('Mon', 2, 'Ph'),
('Mon', 3, 'Mth'),
('Mon', 4, 'CS'),
('Mon', 5, 'Lab1'),
('Mon', 6, 'Lab2'),
('Mon', 7, 'Lab3'),
('Tue', 1, 'Ph'),
('Tue', 2, 'Ele'),
('Tue', 3, 'Hu'),
('Tue', 4, 'Ph'),
('Tue', 5, 'En'),
('Tue', 6, 'CS2'),
('Tue', 7, 'Mth')
) AS X (Day,   Period,    Subject)
)

SELECT Day, [1] AS P1, [2] AS P2,[3] AS P3, [4] AS P4, [5] AS P5,[6] AS P6,[7] AS P7
FROM ExampleData
PIVOT  
(  
Max(Subject)  
FOR Period IN ([1], [2],[3],[4], [5],[6], [7])  
) AS PivotTable; 

结果

Day  P1   P2   P3   P4   P5   P6   P7
---- ---- ---- ---- ---- ---- ---- ----
Mon  Ch   Ph   Mth  CS   Lab1 Lab2 Lab3
Tue  Ph   Ele  Hu   Ph   En   CS2  Mth

答案 2 :(得分:1)

你可以试试......

SELECT DISTINCT Day,
       (SELECT Subject
            FROM my_table mt2
            WHERE mt2.Day = mt.Day AND
                  Period  = 1) AS P1,
       (SELECT Subject
            FROM my_table mt2
            WHERE mt2.Day = mt.Day AND
                  Period  = 2) AS P2,
   .
   .
   etc
   .
   .
   .
   (SELECT Subject
        FROM my_table mt2
        WHERE mt2.Day = mt.Day AND
              Period  = 7) AS P7
FROM my_table mt;

但我不能说我非常喜欢它。但总比没有好。

答案 3 :(得分:1)

使用交叉应用以单个列中的逗号分隔格式获取所有值。而不是“7”不同的列。以下查询可用于任何列 - >行映射

SELECT DISTINCT Day, [DerivedColumn] FROM <Table> A CROSS APPLY ( SELECT Period + ',' FROM <Table> B WHERE A.Day = B.Day Order By Period FOR XML PATH('') ) AS C (DerivedColumn)

你可以在Mon的一列中获得[Ch,Ph,Mth,CS2,Lab1,Lab2,Lab3]等等......你可以用它作为一个表来查询任何特定的日子。

希望这有帮助

答案 4 :(得分:1)

DECLARE @TIMETABLE TABLE (
    [Day]       CHAR(3),
    [Period]    TINYINT,
    [Subject]   CHAR(5)
)
INSERT INTO @TIMETABLE([Day], [Period], [Subject])
VALUES
    ('Mon', 1, 'Ch'),
    ('Mon', 2, 'Ph'),
    ('Mon', 3, 'Mth'),
    ('Mon', 4, 'CS'),
    ('Mon', 5, 'Lab1'),
    ('Mon', 6, 'Lab2'),
    ('Mon', 7, 'Lab3'),
    ('Tue', 1, 'Ph'),
    ('Tue', 2, 'Ele'),
    ('Tue', 3, 'Hu'),
    ('Tue', 4, 'Ph'),
    ('Tue', 5, 'En'),
    ('Tue', 6, 'CS2'),
    ('Tue', 7, 'Mth')

SELECT 
    [Day],
    MAX(CASE [Period] WHEN 1 THEN [Subject] END) AS P1,
    MAX(CASE [Period] WHEN 2 THEN [Subject] END) AS P2,
    MAX(CASE [Period] WHEN 3 THEN [Subject] END) AS P3,
    MAX(CASE [Period] WHEN 4 THEN [Subject] END) AS P4,
    MAX(CASE [Period] WHEN 5 THEN [Subject] END) AS P5,
    MAX(CASE [Period] WHEN 6 THEN [Subject] END) AS P6,
    MAX(CASE [Period] WHEN 7 THEN [Subject] END) AS P7
FROM @TIMETABLE
GROUP BY [Day]

答案 5 :(得分:0)

with pivot_data as
(
select [day], -- groping column
period, -- spreading column
subject -- aggreate column
from pivot_tb
)
select [day],  [1] AS P1, [2] AS P2,[3] AS P3, [4] AS P4, [5] AS P5,[6] AS P6,[7] AS P7
from pivot_data
pivot ( max(subject) for period in ([1], [2],[3],[4], [5],[6], [7]) ) as p;