我需要专家的帮助。我认为我非常了解SQL,至少到目前为止。我正在使用SQL Server,需要构建一个列出每个注册成员的查询,并在单独的列而不是行中显示其guest虚拟机的每个名称。每个成员可以拥有与每个成员相关联的0:N个访客。所以,这是我的表格:
会员表:memberID(PK),FName,LName,...
访客表:GuestID(PK),FName,LastName,...
事件表:GuestID(PK),MemberID(PK),...
我正在尝试构建一个这样的查询输出:
会员ID | Member_FName | Member_LName | Guest1ID | Guest1_Fname | Guest2ID | Guest2_FName ...
示例:
Member Table
MemberID | FName | LName
001 Frank Smith
002 Mary Jane
003 John Henry
Guest Table
GuestID | FName | LName
101 Steve Smith
102 Peter Smith
103 Mike Jane
Event Table
MemberID | GuestID
001 101
001 102
002 103
输出:
MemberID | FName | LName| GuestID1 | FName1 | LName1 |GuestID2 | FName2 | LName2
001 Frank Smith 101 Steve Smith 102 Peter Smith
002 Mary Jane 103 Mike Jane
003 John Henry
如果我需要提供其他信息,请与我们联系。
提前感谢!
答案 0 :(得分:3)
您可以同时实施UNPIVOT
和PIVOT
功能以获得结果。 UNPIVOT
获取您的列并将数据转换为行,并使用最终结果并将其转换回列:
select MemberID,
memberfirst,
memberlast,
isNull(GuestId_1, '') GuestId_1,
isNull(fname_1, '') fname_1,
isNull(lname_1, '') lname_1,
isNull(GuestId_2, '') GuestId_2,
isNull(fname_2, '') fname_2,
isNull(lname_2, '') lname_2
from
(
select MemberID,
memberfirst,
memberlast,
col+'_'+cast(rn as varchar(10)) col,
value
from
(
select m.MemberID,
m.fname MemberFirst,
m.lname MemberLast,
isNull(cast(g.GuestID as varchar(5)), '') GuestId,
isNull(g.fname, '') fname,
isNull(g.lname, '') lname,
row_number() over(partition by m.parentid order by g.guestid) rn
from member m
left join Event r
on m.parentid = r.memberid
left join guest g
on r.guestid = g.guestid
) src
unpivot
(
value
for col in (GuestId, fname, lname)
) unpiv
) src1
pivot
(
max(value)
for col in (GuestId_1, fname_1, lname_1,
GuestId_2, fname_2, lname_2)
) piv
如果你提前知道记录的数量,上面的工作很有用,但如果没有,那么你会想要使用动态的sql:
DECLARE @query AS NVARCHAR(MAX),
@colsPivot as NVARCHAR(MAX),
@colsPivotNull as NVARCHAR(MAX)
select @colsPivot = STUFF((SELECT ','
+ quotename(c.name +'_'+ cast(t.rn as varchar(10)))
from
(
select cast(row_number() over(partition by m.MemberID order by g.guestid) as varchar(50)) rn
from member m
left join Event r
on m.parentid = r.memberid
left join guest g
on r.guestid = g.guestid
) t
cross apply sys.columns as C
where C.object_id = object_id('guest')
group by c.name, t.rn
order by t.rn
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select @colsPivotNull = STUFF((SELECT ', IsNull('
+ quotename(c.name +'_'+ cast(t.rn as varchar(10)))+', '''') as '+c.name +'_'+ cast(t.rn as varchar(10))
from
(
select cast(row_number() over(partition by m.MemberID order by g.guestid) as varchar(50)) rn
from member m
left join Event r
on m.parentid = r.memberid
left join guest g
on r.guestid = g.guestid
) t
cross apply sys.columns as C
where C.object_id = object_id('guest')
group by c.name, t.rn
order by t.rn
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query
= 'select
MemberID,
memberfirst,
memberlast, '+@colsPivotNull+'
from
(
select MemberID,
memberfirst,
memberlast,
col+''_''+cast(rn as varchar(10)) col,
value
from
(
select m.MemberID,
m.fname MemberFirst,
m.lname MemberLast,
isNull(cast(g.GuestID as varchar(5)), '''') GuestId,
isNull(g.fname, '''') fname,
isNull(g.lname, '''') lname,
row_number() over(partition by m.parentid order by g.guestid) rn
from member m
left join Event r
on m.parentid = r.memberid
left join guest g
on r.guestid = g.guestid
) x
unpivot
(
value
for col in (GuestId, fname, lname)
) u
) x1
pivot
(
max(value)
for col in ('+ @colspivot +')
) p'
exec(@query)
两个版本都会产生相同的结果:
| MemberID | MEMBERFIRST | MEMBERLAST | GUESTID_1 | FNAME_1 | LNAME_1 | GUESTID_2 | FNAME_2 | LNAME_2 |
-------------------------------------------------------------------------------------------------------
| 1 | Frank | Smith | 101 | Steve | Smith | 102 | Peter | Smith |
| 2 | Mary | Jane | 103 | Mike | Jane | | | |
| 3 | John | Henry | | | | | | |
答案 1 :(得分:0)
实际上,为guest虚拟机创建一列并使用逗号分隔列表更容易。
你可以这样做:
SELECT DISTINCT memberID, FName, LName,
STUFF((SELECT ', ' + FName + ' ' + LName + ' ('+GuestID+')'
FROM Relationship R
JOIN Guest G ON R.GuestID = G.GuestID
WHERE R.MemberID = Memeber.MemberID
FOR XML PATH ('')),1,2,'') AS GuestList
FROM Member
看起来像这样:
MemberID | FName | LName| GuestList
001 Frank Smith Steve Smith (101), Peter Smith (102)
002 Mary Jane Mike Jane (103)
003 John Henry