How to pivot rows into columns (custom pivoting)

前端 未结 6 1803
夕颜
夕颜 2020-11-27 05:27

I have a Sql Database table similar to the following:

Day   Period    Subject

Mon   1         Ch
Mon   2         Ph
Mon   3         Mth
Mon   4         CS
M         


        
相关标签:
6条回答
  • 2020-11-27 05:43

    You could try...

    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;
    

    but I can't say I like it very much. Better than nothing, though.

    0 讨论(0)
  • 2020-11-27 05:46
    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;
    
    0 讨论(0)
  • 2020-11-27 05:51

    Use cross apply to get all the values in a comma delimted format in a single column. instead of "7" different columns. The following query can be used for any column-> row mapping

    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)
    

    You will get [Ch,Ph,Mth,CS2,Lab1,Lab2,Lab3] in one column for Mon and so on ... You could use this as a table to query for any particular Day.

    Hope this helps

    0 讨论(0)
  • 2020-11-27 05:53
    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]
    
    0 讨论(0)
  • 2020-11-27 06:00

    You could probably do it with the PIVOT function, but I prefer the old school method:

    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
    
    • I changed some column names to avoid reserved words
    0 讨论(0)
  • 2020-11-27 06:00

    Just incase you do want the new school method. (The Pivot statement should work in SQL2005+, the VALUES bit for the example data only 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; 
    

    Result

    Day  P1   P2   P3   P4   P5   P6   P7
    ---- ---- ---- ---- ---- ---- ---- ----
    Mon  Ch   Ph   Mth  CS   Lab1 Lab2 Lab3
    Tue  Ph   Ele  Hu   Ph   En   CS2  Mth
    
    0 讨论(0)
提交回复
热议问题