【问题标题】:Combining/merging multiple columns unique values in a single row在单行中组合/合并多列唯一值
【发布时间】:2018-10-08 16:01:22
【问题描述】:

尝试将多个列和行与 SSMS 中的单个查询组合在一起。这是我正在使用的更复杂表的更简单版本:

这是我当前的查询:

CREATE TABLE Table1
([C1] varchar(50), [C2] varchar(50), [C3] varchar(50))
;

INSERT INTO Table1
([C1], [C2], [C3])
VALUES
('F92', 'Game1', 'b100'),
('F92', 'Game1', 'b200'),
('F92', 'Game2', 'C200'),
('F92', 'Game2', 'D400')
;



SELECT
 C1,C2,
 STUFF(
     (SELECT ', ' + C3
      FROM Table1
      WHERE C1 = a.C1 AND C2 = a.C2
      FOR XML PATH (''))
      , 1, 1, '')  AS NamesList
FROM Table1 AS a
GROUP BY C1,C2

drop table table1

我打算得到如下结果:

C1   | Namelist
F92  | Game1 b100, b200 Game2 c200, d400

这在单个查询中可行吗?

【问题讨论】:

  • 发布 ddl、示例数据和所需输出的工作真是太棒了。当您努力发布这么多信息时,它真的很容易提供帮助。

标签: sql-server tsql grouping ssms aggregate-functions


【解决方案1】:

扩展这个例子。这是新的查询:

            CREATE TABLE Table1
            ([C1] varchar(50), [C2] varchar(50), [C3] varchar(50),[C4] varchar(50),[C5] varchar(50) )
            ;

            INSERT INTO Table1
            ([C1], [C2], [C3], [C4], [C5])
            VALUES
            ('F92', 'XBOX','81-94','Game1', 'B350'),
            ('F92', 'XBOX','81-94','Game1', 'B150'),
            ('F92', 'XBOX','76-80','Game2', 'PB100'),
            ('F92', 'XBOX','76-80','Game2', 'PB200'),
            ('F92', 'XBOX','95-97','Game2', 'PB300')
            ;

            with FirstPass as
            (
                SELECT
                 C1, c2, 
                    c3 + ' ' + c4+ + STUFF(
                     (SELECT ', ' +''+ c5
                      FROM Table1
                      WHERE C1 = a.C1 AND C2 = a.C2  AND C3 = a.C3  AND C4 = a.C4  
                      FOR XML PATH (''))
                      , 1, 1, '')  AS NamesList
                , count(*) as GameCount
                FROM Table1 AS a
                GROUP BY C1,C2,c3, c4
            )

            select distinct C1,C2
                , NameList = stuff((select ' ' + fp2.NamesList
                    from FirstPass fp2
                    where fp.C1 = fp2.C1
                    group by fp2.GameCount, fp2.NamesList
                    order by fp2.GameCount
                    FOR XML PATH('')), 1, 1, '')
                    into table2
            from FirstPass fp

            -- concatenate and insert into existing table

            insert into table2 (C1, conc)
            select C1, C2 + ' ' + NameList
            from FirstPass fp

            SELECT *  FROM table2


            drop table table1
            drop table table2

想要的结果:

C1  |conc
F92 |XBOX 95-97 GAME2 PB300 76-80 GAME2 PB100, PB200 81-94 GAME1 B350, B150

并将此结果插入现有表“table2”

在这里连接最好的解决方案是否达到了预期的结果?查询的这一部分让我失望:

-- concatenate and insert into existing table

            insert into table2 (C1, conc)
            select C1, C2 + ' ' + NameList
            from FirstPass fp

【讨论】:

    【解决方案2】:

    当然可以。您可以使用 cte 来获取您已经获得的分隔列表。然后获取结果并将其转换为另一个分隔列表。但是您可能需要一些东西作为组之间的分隔符,而不是空格。

    with FirstPass as
    (
        SELECT
         C1,
         C2 + ' ' + STUFF(
             (SELECT ', ' + C3
              FROM Table1
              WHERE C1 = a.C1 AND C2 = a.C2
              FOR XML PATH (''))
              , 1, 1, '')  AS NamesList
        FROM Table1 AS a
        GROUP BY C1,C2
    )
    
    select C1
        , NameList = stuff((select ' ' + fp2.NamesList
            from FirstPass fp2
            where fp.C1 = fp2.C1
            FOR XML PATH('')), 1, 1, '')
    from FirstPass fp
    group by fp.C1
    

    返回:

    F92 |游戏1 b100、b200 游戏2 C200、D400

    --编辑--

    根据需要按计数对 C2 进行排序的新要求,您可以简单地添加一点聚合。这与原来的变化不大。

    with FirstPass as
    (
        SELECT
         C1,
         C2 + ' ' + STUFF(
             (SELECT ', ' + C3
              FROM Table1
              WHERE C1 = a.C1 AND C2 = a.C2
              FOR XML PATH (''))
              , 1, 1, '')  AS NamesList
        , count(*) as GameCount
        FROM Table1 AS a
        GROUP BY C1,C2
    )
    
    select distinct C1
        , NameList = stuff((select ' ' + fp2.NamesList
            from FirstPass fp2
            where fp.C1 = fp2.C1
            group by fp2.GameCount, fp2.NamesList
            order by fp2.GameCount desc
            FOR XML PATH('')), 1, 1, '')
    from FirstPass fp
    

    【讨论】:

    • 感谢就像一个魅力。所以这是我陷入困境的另一点(不知道我是否应该创建一个新票)。
    • 如果可行,您应该考虑将其标记为答案。
    【解决方案3】:

    说现在的值是

     VALUES
    ('F92', 'Game1', 'b100'),
    ('F92', 'Game1', 'b200'),
    ('F92', 'Game2', 'C200'),
    ('F92', 'Game2', 'D400'),
    ('F92', 'Game2', 'D500')
    ;
    

    所以现在 Game2 出现了 3 次。使用 Sean Lange 的代码结果按升序排列,因此 Game1 出现在 Game2 之前。有没有办法根据 c2 列的计数(降序)显示结果,所以预期的结果是

    F92 | Game2 C200, D400, D500 Game1 b100, b200 
    

    【讨论】:

      猜你喜欢
      • 2020-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-07
      相关资源
      最近更新 更多