SQL Server将行转换为相关表的动态列

时间:2014-09-15 14:52:31

标签: sql sql-server sql-server-2008

我在将行转换为动态列时遇到问题,我有以下结构:

用户(表默认值)

UserID  UserName
1       First User Name
2       Second User Name

UserRegion(关系:用户)

UserID  RegionID
1       1
1       2
1       3
2       1
2       2
2       3

RegionLanguage

RegionID  LanguageID  RegionName
1         1           Region Name 1
2         1           Region Name 2
3         1           Region Name 3
4         1           Region Name 4
5         2           Region Name 5
6         3           Region Name 6

我的困难是根据RegionLanguage表的返回创建动态列的结构。 我的“Where”子句是RegionLanguage.LanguageID = 1,如果用户和区域之间存在关系(表UserRegion),则RegionLanguage.RegionName的“Case”为“Yes”。

所需的输出是:

UserID  UserName           Region Name 1   Region Name 2   Region Name 3   Region Name 4
1       First User Name    Yes             Yes             Yes             No
2       Second User Name   Yes             Yes             Yes             No

我正在使用SQL Server 2008。

1 个答案:

答案 0 :(得分:0)

这里有几种选择。根据您的要求,您可以执行以下操作:

多次加入区域表。如果您只有4个左右的列,这很好。然后用一些CASE逻辑汇总数据。这可能是最简单的方法,但可能缺少您需要的功能,或者不足以导致大量复制粘贴的可能注释。

枢轴。一旦掌握了它,这非常好,但开始时可能有点令人生畏。查看一些示例并熟悉PIVOT命令,然后你就可以搞清楚了。有更多的功能,不会让你复制过去的戏剧。

多个子查询。你可能不希望这样,但这是可能的。

动态SQL。比以前更糟糕,因为有替代方案你应该使用它。只需将其列为完整答案即可。

以下是此方案的一个简单示例:

select name
    , max(case when [Region Name 1] is null then 0 else 1 end) [Region Name 1]
    , max(case when [Region Name 2] is null then 0 else 1 end) [Region Name 2]
    , max(case when [Region Name 3] is null then 0 else 1 end) [Region Name 3]
    , max(case when [Region Name 4] is null then 0 else 1 end) [Region Name 4]
    , max(case when [Region Name 5] is null then 0 else 1 end) [Region Name 5]
    , max(case when [Region Name 6] is null then 0 else 1 end) [Region Name 6]

from 
(select [user].name, RegionName, RegionName r2 from (values 
    (1,'First User Name'),
    (2, 'Second User Name')) [user](id, name)
left join (values
    (1, 1),
    (1, 3),
    (1, 3),
    (2, 4),
    (2, 1),
    (2, 6))
UserRegion(UserID,  RegionID)
    on [user].id = UserRegion.UserID
left join (values
    (1 ,1, 'Region Name 1'),
    (2 ,1, 'Region Name 2'),
    (3 ,1, 'Region Name 3'),
    (4 ,1, 'Region Name 4'),
    (5 ,2, 'Region Name 5'),
    (6 ,3, 'Region Name 6'))
RegionLanguage(RegionID, LanguageID, RegionName)
    on UserRegion.RegionID = RegionLanguage.RegionID) sub

PIVOT
(
MAX(RegionName)
FOR RegionName IN ( [Region Name 1]
    , [Region Name 2]
    , [Region Name 3]
    , [Region Name 4]
    , [Region Name 5]
    , [Region Name 6]   )
) AS PivotTable
group by name