在 SQL 中将行转换为列

Posted

技术标签:

【中文标题】在 SQL 中将行转换为列【英文标题】:Convert rows to columns in SQL 【发布时间】:2012-12-01 20:09:36 【问题描述】:

请问我该怎么做?

【问题讨论】:

您使用的是哪个数据库系统? 发布您正在使用的表结构以及 Yogendra 提出的问题。 你是如何确定你想要C 10 18 0 9而不是(比如说)C 18 10 9 0 我使用 Microsoft SQL Server Express。 亲爱的 ruakh,没有特别的顺序。 【参考方案1】:

您可以使用PIVOT 表运算符将这些课程成绩的行转换为列,如下所示:

SELECT  
  Course, 
  [1] AS "Grade 1", 
  [2] AS "Grade 2", 
  [3] AS "Grade 3", 
  [4] AS "Grade 4"
FROM
(
  SELECT 
    Course, 
    Grade, 
    ROW_NUMBER() OVER(PARTITION BY Course 
                      ORDER BY COURSE) rownum 
  FROM Grades
) t
PIVOT 
(
   MAX(Grade)
   FOR rownum IN([1], [2], [3], [4])
) p;

SQL Fiddle Demo

这会给你:

COURSE    GRADE 1   GRADE 2      GRADE 3     GRADE 4
  A         15        17          (null)     (null)
  B         12      (null)        (null)     (null)
  C         10        18            0           9

注意:我使用排名函数ROW_NUMBER()PARTITION BY Course 将它们划分为四个等级。这样您就可以将它们分成这四组。

如果您需要动态处理,以防有未知数量的成绩。在这种情况下,您可以使用动态 SQL 来动态生成成绩列表,如下所示:

DECLARE @cols AS NVARCHAR(MAX);
DECLARE @query AS NVARCHAR(MAX);

SELECT @cols = STUFF((SELECT distinct ',' 
                        + QUOTENAME('Grade ' 
                        + CAST(ROW_NUMBER() OVER(PARTITION BY Course 
                                               ORDER BY Course) AS VARCHAR(10)))
                FROM Grades
                         FOR XML PATH(''), TYPE
                      ).value('.', 'NVARCHAR(MAX)'), 1, 1, '');

SELECT @query = 'SELECT Course, ' + @cols +  
                'FROM
                 (
                   SELECT 
                     Course, 
                     Grade, 
                     ''Grade '' + CAST(ROW_NUMBER() 
                                       OVER(PARTITION BY Course 
                                ORDER BY COURSE) AS VARCHAR(10)) rownum 
                   FROM Grades
                 ) t
                 PIVOT 
                 (
                   MAX(Grade)
                   FOR rownum IN(' + @cols + ')' +
                ') p';
execute(@query);

Dynamic SQL Fiddle Demo

【讨论】:

我会用 dense_rank() 改变 row_number,所以如果有双 15 标记,它不会像dense_rank() OVER(PARTITION BY Course ORDER BY Grade) 那样显示在枢轴中

以上是关于在 SQL 中将行转换为列的主要内容,如果未能解决你的问题,请参考以下文章

如何在sql中将行转换为列

如何在 SQL Server 或 C# 代码中将行转换为列

如何在 SQL Server 中将行动态转换为列

在 Spark SQL (pyspark) 中将行转置为列

在 Redshift 中将多行转换为列

在实体框架中将行转换为列