SQL在水平选择中连接

时间:2015-10-08 11:04:33

标签: sql sql-server sql-server-2014

你能帮帮我吗?我使用下面指出的SQL:

SELECT 
    DISTINCT C.Field1 As 'Group',
    A.Field2 As 'Security Object'
    E.Field3 As 'User'
FROM TableA AS A
JOIN TableB AS B ON B.key1 = A.Key1
JOIN TableC AS C ON C.Key1 = B.key2
JOIN TableD AS D ON D.key1 = C.key2
where A.Field1 = 'ObjectA'
GROUP BY C.Field1, A.Field2, E.Field3

典型输出

Group   Security Object User
Group1  ObjectA UserA
Group1  ObjectA UserB
Group1  ObjectA UserC
Group2  ObjectA UserE
Group2  ObjectA UserF
Group2  ObjectA UserH
etc...

我想输出更像:

的内容
Group   Security Object User
Group1  ObjectA UserA, UserB, UserC
Group2  ObjectA UserE, UserF, UserH
etc

但是,我很难以指示的水平形式连接用户字段。你能帮我吗? 我知道有很多关于这个在线,但没有什么工作正常:-( 学家

2 个答案:

答案 0 :(得分:1)

这是一个不使用像pivot这样的解决方案。从所有用户名,我只需构建一个逗号列表。该示例不使用您的SQL,而是使用结果集并提供所需的输出:

Group1  ObjectA   UserA, UserB, UserC
Group2  ObjectA   UserE, UserF, UserH

我重命名了一些列名以避免关键字冲突。 这个SQL中有趣的部分是使用 for xmlpath ,这是使用SQLServer提供逗号列表的方式。

select 
distinct 
group2, security,
substring((select ', ' + user2 from table1 t 
    where t.group2=table1.group2 and t.security=table1.security 
    order by t.user2
    for xml path('')), 3, 10000) as User_List
from table1

http://sqlfiddle.com/#!6/61b9b6/4

如果还有其他更好的方法,也许是SQLServer 2014中的新方法,我很想听。

答案 1 :(得分:0)

我已经设置了以下示例来演示

  1. 使用带有FOR XML PATH的APPLY运算符。我使用了OUTER APPLY,因为有一个用户无权访问对象。
  2. 在下面的第一个查询中,我避免在结果中使用“XML实体”。请注意,对象名称包含XML需要形成XML的字符。然后,下面的第二个查询显示如果TYPE和.value(...被省略,则会发生什么。
  3. SQL Fiddle

    MS SQL Server 2014架构设置

    CREATE TABLE Users  
        ([Code] varchar(1), [UserName] varchar(4))
    ;
    
    INSERT INTO Users   
        ([Code], [UserName])
    VALUES
        ('A', 'Aaaa'),
        ('B', 'Bbbb'),
        ('C', 'Cccc'),
        ('D', 'Dddd'),
        ('E', 'Eeee')
    ;
    
    
    CREATE TABLE Objects    
        ([Code] varchar(7), [Name] varchar(23))
    ;
    
    INSERT INTO Objects 
        ([Code], [Name])
    VALUES
        ('ObjectA', 'Fred & Ginger Whizzbang'),
        ('ObjectB', 'The diamond<> cutter'),
        ('ObjectC', 'Whatever'),
        ('ObjectD', 'Blah de Blah')
    ;
    
    CREATE TABLE ObjectAccess
        ([ID] int, [ObjectCode] varchar(7), [UserCode] varchar(1))
    ;
    
    INSERT INTO ObjectAccess
        ([ID], [ObjectCode], [UserCode])
    VALUES
        (1, 'ObjectA', 'A'),
        (2, 'ObjectA', 'B'),
        (3, 'ObjectA', 'C'),
        (4, 'ObjectB', 'D'),
        (5, 'ObjectB', 'A'),
        (6, 'ObjectB', 'B'),
        (7, 'ObjectB', 'C'),
        (8, 'ObjectC', 'B'),
        (9, 'ObjectC', 'C'),
        (10, 'ObjectC', 'D'),
        (11, 'ObjectD', 'C'),
        (12, 'ObjectD', 'D'),
        (13, 'ObjectE', 'A'),
        (14, 'ObjectF', 'D')
    ;
    

    查询1

    SELECT
          Users.code
        , Users.UserName
        , oa.ObjectList
    FROM Users
          OUTER APPLY (
                SELECT
                      STUFF
                      ((
                            SELECT /* DISTINCT -- can be used here if required */
                                  ',' + Objects.Name
                            FROM ObjectAccess
                                  INNER JOIN Objects ON ObjectAccess.ObjectCode = Objects.Code
                            WHERE ObjectAccess.UserCode = Users.Code
                            ORDER BY Objects.Name
                            FOR XML PATH (''), TYPE --<< nb!!
                      )
                      .value('.', 'varchar(max)') --<< nb!!
                      , 1, 1, '')
          ) AS oa (ObjectList)
    

    <强> Results

    | code | UserName |                                                         ObjectList |
    |------|----------|--------------------------------------------------------------------|
    |    A |     Aaaa |                       Fred & Ginger Whizzbang,The diamond<> cutter |
    |    B |     Bbbb |              Fred & Ginger Whizzbang,The diamond<> cutter,Whatever |
    |    C |     Cccc | Blah de Blah,Fred & Ginger Whizzbang,The diamond<> cutter,Whatever |
    |    D |     Dddd |                         Blah de Blah,The diamond<> cutter,Whatever |
    |    E |     Eeee |                                                             (null) |
    

    查询2

    SELECT
          Users.code
        , Users.UserName
        , oa.ObjectList
    FROM Users
          OUTER APPLY (
                SELECT
                      STUFF
                      ((
                            SELECT /* DISTINCT -- can be used here if required */
                                  ',' + Objects.Name
                            FROM ObjectAccess
                                  INNER JOIN Objects ON ObjectAccess.ObjectCode = Objects.Code
                            WHERE ObjectAccess.UserCode = Users.Code
                            ORDER BY Objects.Name
                            FOR XML PATH ('')
                      )
                      , 1, 1, '')
          ) AS oa (ObjectList)
    

    <强> Results

    | code | UserName |                                                                   ObjectList |
    |------|----------|------------------------------------------------------------------------------|
    |    A |     Aaaa |                       Fred &amp; Ginger Whizzbang,The diamond&lt;&gt; cutter |
    |    B |     Bbbb |              Fred &amp; Ginger Whizzbang,The diamond&lt;&gt; cutter,Whatever |
    |    C |     Cccc | Blah de Blah,Fred &amp; Ginger Whizzbang,The diamond&lt;&gt; cutter,Whatever |
    |    D |     Dddd |                             Blah de Blah,The diamond&lt;&gt; cutter,Whatever |
    |    E |     Eeee |                                                                       (null) |