2012-11-27 68 views
2

我想連接SQL Server 2008 R2中的三個表,我希望將第二個表中的項添加爲新列。與行連接表

詳細講解 - 我有3個表:

第一個表包含用戶名和用戶ID

UserID UserName 
1  Mike 
2  John 
3  George 

第二個表是位置ID與位置名稱

PositionID PositionName 
1   RW 
2   LW 
3   DF 
4   MDF 
5   SS 
6   CF 
etc 

三表表格包含他們的首選位置,其中一位用戶可以有多個位置

UserID PositionId 
1  1 
1  3 
2  2 
2  3 
2  5 
3  2 
3  7 

當我加入這些表我想對每一位用戶單行所有的首選位置像

UserID UserName PreferedPosition PreferedPosition2 PreferedPosition3 
1  Mike  RW    LW    
2  John  CMF    SS    CF 
3  George LW    MDF 

我不知道如何做到這一點,任何幫助,將不勝感激。

回答

2

如果你有位置的只有幾個數字,你可以用PIVOT關鍵字

select 
    UserID, 
    UserName, 
    [1] as Position1, 
    [2] as Position2, 
    [3] as Position3 
from 
(
    select 
     U.UserID, U.UserName, P.PositionName, 
     row_number() over (partition by U.UserID order by P.PositionName) as RowNum 
    from Positions_Users as PU 
     inner join Positions as P on P.PositionID = PU.PositionID 
     inner join Users as U on U.UserID = PU.UserID 
) as P 
    pivot 
    (
     min(P.PositionName) 
     for P.RowNum in ([1], [2], [3]) 
    ) as PIV 

SQL FIDDLE

做到這一點。然而,如果你想擁有列的動態數量,你必須使用動態SQL,這樣

declare @stmt nvarchar(max), @stmt_columns1 nvarchar(max), @stmt_columns2 nvarchar(max) 
declare @Temp_Data table (RowNum nvarchar(max)) 

insert into @Temp_Data 
select distinct row_number() over (partition by U.UserID order by P.PositionName) as RowNum 
from Positions_Users as PU 
    inner join Positions as P on P.PositionID = PU.PositionID 
    inner join Users as U on U.UserID = PU.UserID 

select @stmt_columns1 = stuff((select ', [' + RowNum + ']' from @Temp_Data for xml path(''), type).value('.', 'nvarchar(max)'), 1, 2, '') 
select @stmt_columns2 = stuff((select ', [' + RowNum + '] as Position' + RowNum from @Temp_Data for xml path(''), type).value('.', 'nvarchar(max)'), 1, 2, '') 

select @stmt = ' 
select 
    UserID, 
    UserName,' + @stmt_columns2 + ' 
from 
(
    select 
     U.UserID, U.UserName, P.PositionName, 
     row_number() over (partition by U.UserID order by P.PositionName) as RowNum 
    from Positions_Users as PU 
     inner join Positions as P on P.PositionID = PU.PositionID 
     inner join Users as U on U.UserID = PU.UserID 
) as P 
    pivot 
    (
     min(P.PositionName) 
     for P.RowNum in (' + @stmt_columns1 + ') 
    ) as PIV' 

exec sp_executesql @stmt = @stmt 

SQL FIDDLE

+0

非常感謝我正在尋找的 –

+1

您可以通過將''Position''與子選擇中的行號連接來準備最終的列名,如下所示:''Position'+ rtrim(row_number()over ... )as ...'而不是'row_number()... as ...'。這樣,您只需要生成一個列列表('Position1,Position2 ...')並使用它兩次(在PIVOT和主SELECT中)。 –

+0

@AndriyM好點,如果它是生產代碼,我肯定會重寫它的方式 –