从数据库表中展平数据

问题描述 投票:0回答:3

我有表格形式的数据:

Grade |  TimeInterval |  SubjectName
1        0               History
1        1               Chemistry
1        3               Biology
2        0               Maths
2        2               Biology
2        3               History
3        0               Biology
3        1               History
3        2               Chemistry
3        3               Maths

我想将上述数据转换成以下格式,最好的方法是什么。

Grade TimeInterval0 TimeInterval1 TimeInterval2 TimeInterval3
1     History       Chemistry     Empty         Biology
2     Maths         Empty          Biology      History
3     Biology       History        Chemistry    Maths

我不知道是否可以直接使用PIVOT转换,因为原始源数据中的TimeInterval将变为0,1,2而在我的展平目标表中,列名称被指定为TimeInterval0,TimeInterval1,TimeInterval2等。

我无法更改架构,因为它已经有很多数据,而且许多其他表彼此相互关联。

sql sql-server-2012
3个回答
0
投票

您可以随时进行手动转轴。这允许您控制列名等,但您必须自己完成所有的数据透视工作。像这样的东西

Select G.Grade
    , Int0.SubjectName as TimeInterval0
    , Int1.SubjectName as TimeInterval1
    , Int2.SubjectName as TimeInterval2
    , Int3.SubjectName as TimeInterval3
from (Select distinct Grade from SourceTable) G
    left outer join SourceTable Int0 on Int0.Grade = G.Grade and Int0.TimeInterval = 0
    left outer join SourceTable Int1 on Int1.Grade = G.Grade and Int1.TimeInterval = 1
    left outer join SourceTable Int2 on Int2.Grade = G.Grade and Int2.TimeInterval = 2
    left outer join SourceTable Int3 on Int3.Grade = G.Grade and Int3.TimeInterval = 3

0
投票

您始终可以使用外部查询中的列别名重命名列。我在这里使用CTE。

IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp;
CREATE TABLE #temp (Grade INT,  TimeInterval INT, SubjectName VARCHAR(100))

INSERT #temp
(
    Grade,
    TimeInterval,
    SubjectName
)
VALUES
    (1,        0,               'History    '),
    (1,        1,               'Chemistry  '),
    (1,        3,               'Biology    '),
    (2,        0,               'Maths      '),
    (2,        2,               'Biology    '),
    (2,        3,               'History    '),
    (3,        0,               'Biology    '),
    (3,        1,               'History    '),
    (3,        2,               'Chemistry  '),
    (3,        3,               'Maths      ');


WITH pivoted AS (
   SELECT * 
   FROM #temp
   PIVOT ( 
       MAX(SubjectName) FOR TimeInterval IN ([0], [1], [2], [3])
   ) pvt
)
SELECT grade,
       [TimeInterval0] = pivoted.[0],
       [TimeInterval1] = pivoted.[1],
       [TimeInterval2] = pivoted.[2],
       [TimeInterval3] = pivoted.[3]
FROM pivoted

0
投票

间隔时间为0-15,但将来会增加

你需要一个dynamic pivot

CREATE TABLE SampleData (Grade INT,  TimeInterval INT, SubjectName VARCHAR(100))

INSERT SampleData
(
    Grade,
    TimeInterval,
    SubjectName
)
VALUES
    (1,        0,               'History    '),
    (1,        1,               'Chemistry  '),
    (1,        3,               'Biology    '),
    (2,        0,               'Maths      '),
    (2,        2,               'Biology    '),
    (2,        3,               'History    '),
    (3,        0,               'Biology    '),
    (3,        1,               'History    '),
    (3,        2,               'Chemistry  '),
    (3,        3,               'Maths      ');

DECLARE @cols nvarchar(max)

SELECT @cols = STUFF(
                    (SELECT DISTINCT CONCAT(',[', t.TimeInterval, ']') FROM SampleData t FOR XML PATH (''))
                   ,1,1,'')

DECLARE @headers nvarchar(max)

SELECT @headers = STUFF(
                    (SELECT DISTINCT CONCAT(', [' , t.TimeInterval , '] AS [TimeInterval' , t.TimeInterval, ']') FROM SampleData t FOR XML PATH (''))
                   ,1,1,'')

DECLARE @query nvarchar(max) = N'Select [Grade],  ' + @headers + 
        ' FROM 
         (
            SELECT Grade, TimeInterval, SubjectName FROM  SampleData
         ) src
         PIVOT
         (
            MAX(SubjectName) FOR TimeInterval IN ('+ @cols+ ')
         ) pvt
        '
PRINT @query

EXEC (@query)

DROP TABLE SampleData

在这里演示http://rextester.com/LIW80994

© www.soinside.com 2019 - 2024. All rights reserved.