Sql 用行连接表
我正在尝试连接SQLServer2008R2中的三个表,希望第二个表中的项作为新列添加 要详细解释,我有3个表: 第一个表包含用户名和用户IDSql 用行连接表,sql,sql-server-2008,join,Sql,Sql Server 2008,Join,我正在尝试连接SQLServer2008R2中的三个表,希望第二个表中的项作为新列添加 要详细解释,我有3个表: 第一个表包含用户名和用户ID UserID UserName 1 Mike 2 John 3 George 第二个表是带有职位名称的职位ID PositionID PositionName 1 RW 2 LW 3 DF 4 MDF 5 SS 6
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
我不知道如何做到这一点,任何帮助都将不胜感激。如果你只有几个职位,你可以用
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,如下所示
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
您可以通过将
'Position'
与子选择中的行号连接起来来准备最终的列名,类似这样:'Position'+rtrim(row\u number()over…)as…
而不仅仅是row\u number()。。。作为…
。这样,您只需生成一列列表(Position1,Position2…
),并使用它两次(在PIVOT和main SELECT中)。@AndriyM很好,如果它是生产代码,我肯定会这样重写它