取消透视 SQL 表中的所有列

Posted

技术标签:

【中文标题】取消透视 SQL 表中的所有列【英文标题】:Unpivot ALL Columns in a SQL Table 【发布时间】:2014-02-24 19:23:01 【问题描述】:

我有一个包含 30 列的表,我想轻松地取消透视所有列。我知道我可以使用这个策略:

SELECT col, value 
INTO New_Table
FROM
(SELECT * FROM Test_Data) p
UNPIVOT
(value FOR col IN (Column_Name1, Column_Name2... Column_Name30)) as unpvt

我的数据是这样进来的:

Column_Name1    Column_Name2    Column_Name3
Value11         Value21         Value31
Value12         Value22         Value32
Value13         Value23         Value33

这就是我想将它存储在新表中的方式:

New_Column1    New_cloumn2
Column_Name1   Value11
Column_Name1   Value12
Column_Name1   Value13
Column_Name2   Value21
...

但一定有比输入 30 个列名更简单的方法。

提前致谢。

【问题讨论】:

如果您遇到的情况是,实际上应该将 30 列都视为一列是有意义的,这表明您的数据模型首先是严重错误的。为什么应该有一种“更简单的方法”来解决你自己制造的问题? 输入 30 列有多难? @adrianm 30 列都是 32 个字符的代码 @Damien_The_Unbeliever 这是一个 Excel 电子表格的上传,其中每个列标题是一个问题代码,响应如下 是的。 SQL 数据库表与电子表格不同。试图将它们视为同一事物会导致(奇怪的)尝试不恰当地使用它们。此时要学习的主要内容(可能)是表示和存储是两个不同的东西。仅仅因为您在屏幕上看到网格并不意味着数据需要存储在网格中。 【参考方案1】:

这似乎是一个损坏的数据模型,但您可以避免输入列列表。

您可以使用它来生成列列表:

SELECT name
FROM sys.columns
WHERE objecT_id = OBJECT_ID('Test_Data')

还有:

DECLARE @List VARCHAR(MAX) = STUFF((SELECT DISTINCT ',' +   QUOTENAME(name)                     
                                    FROM sys.columns
                                    WHERE objecT_id = OBJECT_ID('Test_Data')                                    
                                    FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)') 
                                    ,1,1,'')
PRINT @List

然后您可以在动态 sql 语句中使用该列表:

DECLARE @List VARCHAR(MAX) = STUFF((SELECT DISTINCT ',' +   QUOTENAME(name)                     
                                    FROM sys.columns
                                    WHERE objecT_id = OBJECT_ID('Test_Data')                                    
                                    FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)') 
                                    ,1,1,'')
        ,@sql VARCHAR(MAX)
SET  @sql  =  'SELECT  col,value  
               INTO New_Table
               FROM  (SELECT  *  FROM  Test_Data)  p
               UNPIVOT (value  FOR  col  IN  ('+@List+'))  as  unpvt
              '
EXEC  (@sql)  

我建议在使用EXEC 之前使用PRINT (@sql) 以确保动态查询是您所追求的。

【讨论】:

以上是关于取消透视 SQL 表中的所有列的主要内容,如果未能解决你的问题,请参考以下文章

在 BigQuery 中的大表中取消透视日期列

对所有具有 null 的列进行取消透视

将日期列取消透视到 Oracle 中复杂查询的单个列

如何按2列取消透视sql表[重复]

使用手动列连接取消透视 T-SQL 查询

在 MySQL 中取消透视多个列