Sql server 合并/合并多列在一行中的唯一值

Sql server 合并/合并多列在一行中的唯一值,sql-server,tsql,grouping,ssms,aggregate-functions,Sql Server,Tsql,Grouping,Ssms,Aggregate Functions,尝试在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', 'C2

尝试在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

这在单个查询中是否可行?

您确定可以做到这一点。您可以使用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

假设现在的值是

 VALUES
('F92', 'Game1', 'b100'),
('F92', 'Game1', 'b200'),
('F92', 'Game2', 'C200'),
('F92', 'Game2', 'D400'),
('F92', 'Game2', 'D500')
;
所以现在游戏2出现了3次。使用肖恩·兰格的代码,结果是按升序排列的,因此游戏1在游戏2之前出现。是否有一种方法可以根据c2列的计数(降序)显示结果,从而使预期结果

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

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

            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
并将此结果插入现有表“表2”

在这里连接最佳解决方案是否达到预期效果?查询的这一部分让我很反感:

-- concatenate and insert into existing table

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

发布ddl、样本数据和所需输出是多么好的工作啊。当你努力发布那么多信息时,这真的很容易帮上忙。谢谢就像一种魅力。所以我还有一个问题(不知道我是否应该创建一张新的票)。如果这是可行的,你应该考虑把它标记为答案。