如何根据特定条件将行分成SQL中的列?

时间:2018-07-13 08:03:16

标签: sql sql-server

我有这样的数据:

Year    Q1      Q2      Q3      Q4
------------------------------------
2000    421     123     145     126
2000    422     124     146     127
2000    423     125     147     128
2000    424     126     148     129
2001    425     127     149     130
2001    426     128     150     131
2001    427     129     151     132
2002    428     130     152     133
2002    429     131     153     134

我如何这样获得它:

Year    Q1      Q2      Q3      Q4      Year    Q1      Q2      Q3      Q4      Year    Q1  Q2  Q3  Q4
--------------------------------------------------------------------------------------------------------
2000    421     123     145     126     2001    425     127     149     130     2002    428 130 152 133
2000    422     124     146     127     2001    426     128     150     131     2002    429 131 153 134
2000    423     125     147     128     2001    427     129     151     132                 
2000    424     126     148     129                                     

我访问了这里:https://www.databasejournal.com/features/mssql/converting-rows-to-columns-pivot-and-columns-to-rows-unpivot-in-sql-server.html 但没有成功。 我可以用PIVOT来做吗,但我却做不到。请给我建议。预先感谢。

1 个答案:

答案 0 :(得分:1)

老实说,这是一个丑陋的解决方案,我真的不知道为什么您希望数据看起来像这样。请注意,ORDER BY子句中的OVER

WITH VTE AS(
    SELECT *
    FROM (VALUES(2000,421,123,145,126),
                (2000,422,124,146,127),
                (2000,423,125,147,128),
                (2000,424,126,148,129),
                (2001,425,127,149,130),
                (2001,426,128,150,131),
                (2001,427,129,151,132),
                (2002,428,130,152,133),
                (2002,429,131,153,134)) V ([Year], Q1, Q2, Q3, Q4)),
RNs AS (
    SELECT *,
           ROW_NUMBER() OVER (PARTITION BY [Year] ORDER BY Q1) AS RN --ORDER BY is total guess
    FROM VTE)
SELECT RN1.[Year], RN1.Q1, RN1.Q2, RN1.Q3, RN1.Q4,
       RN2.[Year], RN2.Q1, RN2.Q2, RN2.Q3, RN2.Q4,
       RN3.[Year], RN3.Q1, RN3.Q2, RN3.Q3, RN3.Q4
FROM RNs RN1
     LEFT JOIN RNs RN2 ON RN1.[Year] = RN2.[Year] - 1
                      AND RN1.RN = RN2.RN
     LEFT JOIN RNs RN3 ON RN1.[Year] = RN3.[Year] - 2
                      AND RN1.RN = RN3.RN
WHERE RN1.[Year] = (SELECT MIN(sq.[Year])
                    FROM RNs sq)
ORDER BY RN1.RN;

如果最低的年份后一年的行数比第一个多(例如,如果2003年有5行,则只能得到4行),这也将无法按预期工作。如果确实需要,可以解决。

编辑:IT仍然很丑陋,但是当以后有更多行时,这会有所帮助:

WITH VTE AS(
    SELECT *
    FROM (VALUES(2000,421,123,145,126),
                (2000,422,124,146,127),
                (2000,423,125,147,128),
                (2000,424,126,148,129),
                (2001,425,127,149,130),
                (2001,426,128,150,131),
                (2001,427,129,151,132),
                (2002,428,130,152,133),
                (2002,429,131,153,134),
                (2003,429,132,154,135),
                (2003,430,133,155,136),
                (2003,431,134,156,137),
                (2003,432,135,157,138),
                (2003,433,136,158,139)) V ([Year], Q1, Q2, Q3, Q4)),
RNs AS (
    SELECT *,
           ROW_NUMBER() OVER (PARTITION BY [Year] ORDER BY Q1) AS RN --ORDER BY is total guess
    FROM VTE),
Tally AS (
    SELECT DISTINCT RNs.RN, Y.MinYear
    FROM RNs
         CROSS APPLY (SELECT MIN(Year) AS MinYear FROM RNs) Y)
SELECT RN1.[Year], RN1.Q1, RN1.Q2, RN1.Q3, RN1.Q4,
       RN2.[Year], RN2.Q1, RN2.Q2, RN2.Q3, RN2.Q4,
       RN3.[Year], RN3.Q1, RN3.Q2, RN3.Q3, RN3.Q4,
       RN4.[Year], RN4.Q1, RN4.Q2, RN4.Q3, RN4.Q4
FROM Tally T
     LEFT JOIN RNs RN1 ON T.RN = RN1.RN
                      AND RN1.[Year] = T.MinYear
     LEFT JOIN RNs RN2 ON T.MinYear = RN2.[Year] - 1
                      AND T.RN = RN2.RN
     LEFT JOIN RNs RN3 ON T.MinYear = RN3.[Year] - 2
                      AND T.RN = RN3.RN
     LEFT JOIN RNs RN4 ON T.MinYear = RN4.[Year] - 3
                      AND T.RN = RN4.RN
ORDER BY T.RN;