显示1行有多个选项的人

时间:2018-03-19 10:44:58

标签: sql-server tsql dynamic pivot

我面临的问题是,我正在寻找一种方法来实现以下目标:

我需要为每个人获得1行,其中的列显示哪些组已链接到此人。我得到了以下3个表

  1. 人员 - 包含人员数据
  2. 群组 - 包含群组数据
  3. 链接 - 包含人员和群组之间的链接
  4. 示例数据(脚本):

    Create table persons (uniqueid int, email varchar(50))
    Create table groups (uniqueid int, title varchar(50))
    Create table link (uniqueid int, groupid int, personid int)
    
    insert into persons (uniqueid, email) values (1, 'firstname1.lastname1@domain.com'), (2, 'firstname2.lastname2@domain.com'), (3, 'firstname3.lastname3@domain.com')
    insert into groups (uniqueid, title) values (1, 'Servicedesk'), (2, 'SecondLine'), (3, 'ThirdLine')
    insert into link (uniqueid, groupid, personid) values (1, 1, 1), (2, 1, 2), (3, 1, 3), (4, 2, 1), (5, 3, 2), (6, 1, 3)
    

    当前查询:

    select p.email, g.title
    FROM link as l
        left join groups g on l.groupid = g.uniqueid
        left join persons p on l.personid = p.uniqueid
    group by p.email, g.title
    

    输出当前查询:

    email                           title
    firstname1.lastname1@domain.com SecondLine
    firstname1.lastname1@domain.com Servicedesk
    firstname2.lastname2@domain.com Servicedesk
    firstname2.lastname2@domain.com ThirdLine
    firstname3.lastname3@domain.com Servicedesk
    

    预期的最终结果:

    email                           Group1       Group2       Group3       
    firstname1.lastname1@domain.com Servicedesk  SecondLine   NULL
    firstname2.lastname2@domain.com Servicedesk  NULL         NULL
    firstname3.lastname3@domain.com Servicedesk  NULL         NULL
    

    要开始尝试解决这个问题,我尝试使用FOR XML PATH ('')为每个人创建1行,所有组都在1列中,但这会在我的生产环境中生成错误Column name 'Email Address' contains an invalid XML identifier as required by FOR XML; ' '(0x0020) is the first character at fault.。 在这一行之后,我想将它们分成列。 目前,我正在寻找正确使用的功能,因此我可以构建完整的查询。

1 个答案:

答案 0 :(得分:3)

您可以动态生成列的名称,并在PIVOT

中使用它
DECLARE @persons TABLE (uniqueid int, email varchar(50))
DECLARE @groups TABLE(uniqueid int, title varchar(50))
DECLARE @link TABLE(uniqueid int, groupid int, personid int)

insert into @persons (uniqueid, email) values (1, 'firstname1.lastname1@domain.com'), (2, 'firstname2.lastname2@domain.com'), (3, 'firstname3.lastname3@domain.com')
insert into @groups (uniqueid, title) values (1, 'Servicedesk'), (2, 'SecondLine'), (3, 'ThirdLine')
insert into @link (uniqueid, groupid, personid) values (1, 1, 1), (2, 1, 2), (3, 1, 3), (4, 2, 1), (5, 3, 2), (6, 1, 3)

SELECT p.*
FROM
(
    select p.email
          ,g.title
          ,'Group'+CAST(ROW_NUMBER() OVER(PARTITION BY p.email ORDER BY (SELECT NULL)) AS varchar(2)) AS ColumnName
    FROM @link as l
        left join @groups g on l.groupid = g.uniqueid
        left join @persons p on l.personid = p.uniqueid
    group by p.email, g.title
) AS tbl
PIVOT
(
    MAX(title) FOR ColumnName IN(Group1,Group2,Group3, Group4 /*add as many as you need*/)
) AS p;

结果

email                           Group1      Group2      Group3  Group4
firstname1.lastname1@domain.com SecondLine  Servicedesk NULL    NULL
firstname2.lastname2@domain.com Servicedesk ThirdLine   NULL    NULL
firstname3.lastname3@domain.com Servicedesk NULL        NULL    NULL