SQL Server 转置数据 - 可能进行数据透视?

Posted

技术标签:

【中文标题】SQL Server 转置数据 - 可能进行数据透视?【英文标题】:SQL Server Transpose Data - Pivot Possibly? 【发布时间】:2014-04-01 18:04:11 【问题描述】:

我一直在寻找一种解决方案,通过元数据查找表将系统中的源数据转换为目标表。我需要一种将源数据转置/转置为列(由各种数据类型组成)的方法。每列的数据类型都列在元数据表中。

表名:SRC

SrcID    AGE    City      Date
------------------------------------
01       32     London    01-01-2013
02       35     Lagos     02-01-2013
03       36     NY        03-01-2013

表名:Metadata

MetaID        Column_Name           Column_type
-------------------------------------------------
11            AGE                   col_integer
22            City                  col_character
33            Date                  col_date

目标表:

要加载到目标表中的源数据(如下图):

目标表:

SrcID     MetaID     col_int     col_char     col_date
---------------------------------------------------------
01        11         32             -            -    
01        22            -        London          -    
01        33            -           -          01-01-2013
02        11         35             -               - 
02        22             -       Lagos              -
02        33             -          -          02-01-2013
03        11         36             -               - 
03        22             -         NY               -
03        33             -          -          03-01-2013

任何帮助将不胜感激。

谢谢,

【问题讨论】:

【参考方案1】:

下面给出的示例查询和步骤。

select srcid, metaid, col_integer, col_character,col_date
from
(
select SrcId, 
CAST(AGE AS NVARCHAR(MAX)) AS AGE, 
CAST(City AS NVARCHAR(MAX)) AS City, 
CAST([Date] AS NVARCHAR(MAX)) AS [Date]
from src
) as dat
unpivot
(
ColVal for Columz IN (AGE, City, [Date])
) as upiv
left join metadata as m
on upiv.Columz = m.Column_name
pivot(
max(ColVal)
for Column_type in ([col_integer], [col_character], [col_date])
) as piv1

用于测试这些查询的示例 SQL 小提琴(适用于 SQL 2008 或更高版本)- http://sqlfiddle.com/#!3/e5e38b/1


如果你想学习,下面给出的步骤 -

第 1 步 -

希望我们可以将 SRC 的年龄列加入元的年龄行。因此,我们使用 unpivot 将 SRC 列转换为行。

select * 
from
(
-- Unpivot query. You need to cast it, 
-- otherwise you get an error
select SrcId, 
CAST(AGE AS NVARCHAR(MAX)) AS AGE, 
CAST(City AS NVARCHAR(MAX)) AS City, 
CAST([Date] AS NVARCHAR(MAX)) AS [Date]
from src
) as dat
unpivot
(
ColVal for Columz IN (AGE, City, [Date])
) as upiv

注意 - 我们为什么要投射?参考这个-UNPIVOT on Table in a Different Server/Database Fails with 'conflicts with the type of other columns' error

输出 -

SrcId, ColVal, Columz
1,32,AGE
1,London,City
1,2013-01-01,Date
2,35,AGE
2,Lagos,City
2,2013-02-01,Date
3,36,AGE
3,NY,City
3,2013-03-01,Date

第 2 步 -

现在我们准备好加入元数据表了。我们只需添加以下连接 到上面的代码 -

left join metadata as m
on upiv.Columz = m.Column_name

输出 -

SrcId,ColVal,Columz,MetaId,Column_Name,Column_Type
1,32,AGE,11,AGE,col_integer
1,London,City,22,City,col_character
1,2013-01-01,Date,33,Date,col_date
2,35,AGE,11,AGE,col_integer
2,Lagos,City,22,City,col_character
2,2013-02-01,Date,33,Date,col_date
3,36,AGE,11,AGE,col_integer
3,NY,City,22,City,col_character
3,2013-03-01,Date,33,Date,col_date

第 3 步 -

我们现在看到我们希望根据您的需要将 Column_Type 列中的那些行转换为列。所以我们使用 PIVOT。我们在上面的代码中加入如下代码

pivot(
max(ColVal)
for Column_type in ([col_integer], [col_character], [col_date])
) as piv1

输出 -

SrcId,Columz,MetaId,Column_Name,col_integer,col_character,col_date
1,AGE,11,AGE,32,NULL,NULL
1,City,22,City,NULL,London,NULL
1,Date,33,Date,NULL,NULL,2013-01-01
2,AGE,11,AGE,35,NULL,NULL
2,City,22,City,NULL,Lagos,NULL
2,Date,33,Date,NULL,NULL,2013-02-01
3,AGE,11,AGE,36,NULL,NULL
3,City,22,City,NULL,NY,NULL
3,Date,33,Date,NULL,NULL,2013-03-01

第 4 步 -

此结果有一些额外的列。要删除多余的列,请将STEP 1 中的第一行更改为select *,即select srcid, metaid, col_integer, col_character,col_date

【讨论】:

以上是关于SQL Server 转置数据 - 可能进行数据透视?的主要内容,如果未能解决你的问题,请参考以下文章

使用数据透视/转置的 SQL Server

Excel或SQL Sserver中数据行列转置/转换?

需要通过 SQL 转置列

SQL Server JSON 将行转置为列

将列转置为行 SQL Server

转置查询创建节点 (SQL Server 2008)