sql - 透视未知列内容

标签 sql sql-server sql-server-2008 pivot

我有以下数据但我之前不知道表格的内容

courses table
-------------
id  | name
-------------
7   | math
99  | geology
4   | ethics
5   | sports
33  | english
29  | math boot camp

我需要输出为

course1_id | course1_name | course2_id | course2_name | course3_id | course3_name
         7 | math         |         99 |      geology |          4 |       ethics

SQLFiddle demo

我试过了

select case when id = 7 then id end as course1_id, 
       case when id = 7 then name end as course1_name
from courses

但这会返回多行而不是一行,并且由于我不知道 id 我无法使用该方法。有什么想法吗?

最佳答案

您需要的 SQL 是:

SELECT  Course1_ID = MAX(CASE WHEN RowNum = 1 THEN ID END),
        Course1_Name = MAX(CASE WHEN RowNum = 1 THEN Name END),
        Course2_ID = MAX(CASE WHEN RowNum = 2 THEN ID END),
        Course2_Name = MAX(CASE WHEN RowNum = 2 THEN Name END),
        Course3_ID = MAX(CASE WHEN RowNum = 3 THEN ID END),
        Course3_Name = MAX(CASE WHEN RowNum = 3 THEN Name END)
FROM    (   SELECT  ID, 
                    Name, 
                    RowNum = ROW_NUMBER() OVER(ORDER BY ID)
            FROM    Courses
        ) C;

但是对于未知的内容,您需要动态生成:

DECLARE @SQL NVARCHAR(MAX) = 'SELECT ' + 
                            STUFF(( SELECT  ',Course' + RowNum + '_ID = MAX(CASE WHEN RowNum = ' + RowNum + ' THEN ID END)
                                            ,Course' + RowNum + '_Name = MAX(CASE WHEN RowNum = ' + RowNum + ' THEN Name END)'
                                    FROM    (   SELECT  RowNum = CAST(ROW_NUMBER() OVER(ORDER BY ID) AS VARCHAR(10))
                                                FROM    Courses
                                            ) c
                                    FOR XML PATH(''), TYPE
                                ).value('.', 'NVARCHAR(MAX)'), 1, 1, '') + 
                                ' FROM (    SELECT  ID, 
                                                    Name, 
                                                    RowNum = ROW_NUMBER() OVER(ORDER BY ID)
                                            FROM    Courses
                                        ) C;'

EXECUTE SP_EXECUTESQL @SQL;

<强> Example on SQL Fiddle


实现相同结果的另一种方法是:

DECLARE @SQL NVARCHAR(MAX) = '';
SELECT   @SQL = @SQL + 
                    ',Course' + RowNum + '_ID = MAX(CASE WHEN RowNum = ' + RowNum + ' THEN ID END)
                    ,Course' + RowNum + '_Name = MAX(CASE WHEN RowNum = ' + RowNum + ' THEN Name END)'
FROM    (   SELECT  RowNum = CAST(ROW_NUMBER() OVER(ORDER BY ID) AS VARCHAR(10))
            FROM    Courses
        ) c;

SET @SQL = 'SELECT ' + STUFF(@SQL, 1, 1, '') + '
            FROM (  SELECT  ID, 
                            Name, 
                            RowNum = ROW_NUMBER() OVER(ORDER BY ID)
                    FROM    Courses
                ) c;';

EXECUTE SP_EXECUTESQL @SQL;

这消除了将行连接成列所需的昂贵的 XML 扩展

<强> Example on SQL Fiddle

如果类(class)顺序完全相关,您只需更改 ROW_NUMBER 函数中的 order by 子句即可。

关于sql - 透视未知列内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20212611/

相关文章:

sql - 如何从 SQL SSIS 中的日期时间字符串中去除日期?

c# - SQLException 未处理。在 GridView 中查看 Excel 文件

sql - 不将查询存储为字符串的动态数据透视查询

sql-server - IN 语句与 PRIMARY KEY 不一致

sql-server-2008 - 如何插入包含单引号字符的字符串?

mysql - 比较 Google BigQuery 中的子串

c# - Entity Framework 打开连接

sql - 比较postgres数据库中的两列

sql-server - 您首选的记录数据库的文档格式是什么

mysql - sql子查询中如何使用Union