【问题标题】:Showing 1 row a person with several options显示 1 行一个人有几个选项
【发布时间】:2018-08-27 21:33:40
【问题描述】:

我面临的问题是我正在寻找一种方法来完成以下任务:

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

  1. 人员 - 包含人员数据
  2. 组 - 包含组数据
  3. 链接 - 包含个人和组之间的链接

示例数据(脚本):

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.。 在这一行之后,我想将它们拆分为列。 目前我正在寻找要使用的正确函数,以便构建完整的查询。

【问题讨论】:

  • 我很困惑如何达到您的预期结果,group2 和 group3 是从哪里派生的?
  • 我有一个函数可以将字符串分成多列。但我还不能将我的数据放入每个电子邮件地址的 1 行中。所以我还没有什么要分开的。

标签: sql-server tsql dynamic pivot


【解决方案1】:

您可以即时生成列的名称并在 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

【讨论】:

  • 很好的答案,还添加了添加更多组的功能,以帮助未来证明 OP 代码 +1
  • 这种动态透视的方式正是我想要的。 +1
猜你喜欢
  • 2017-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多