How to use GROUP BY to concatenate strings in SQL Server?

前端 未结 20 2519
无人及你
无人及你 2020-11-21 04:33

How do I get:

id       Name       Value
1          A          4
1          B          8
2          C          9

to

id               


        
相关标签:
20条回答
  • 2020-11-21 04:51

    If it is SQL Server 2017 or SQL Server Vnext, SQL Azure you can use string_agg as below:

    select id, string_agg(concat(name, ':', [value]), ', ')
    from #YourTable 
    group by id
    
    0 讨论(0)
  • 2020-11-21 04:52

    Eight years later... Microsoft SQL Server vNext Database Engine has finally enhanced Transact-SQL to directly support grouped string concatenation. The Community Technical Preview version 1.0 added the STRING_AGG function and CTP 1.1 added the WITHIN GROUP clause for the STRING_AGG function.

    Reference: https://msdn.microsoft.com/en-us/library/mt775028.aspx

    0 讨论(0)
  • 2020-11-21 04:55

    No CURSOR, WHILE loop, or User-Defined Function needed.

    Just need to be creative with FOR XML and PATH.

    [Note: This solution only works on SQL 2005 and later. Original question didn't specify the version in use.]

    CREATE TABLE #YourTable ([ID] INT, [Name] CHAR(1), [Value] INT)
    
    INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (1,'A',4)
    INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (1,'B',8)
    INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (2,'C',9)
    
    SELECT 
      [ID],
      STUFF((
        SELECT ', ' + [Name] + ':' + CAST([Value] AS VARCHAR(MAX)) 
        FROM #YourTable 
        WHERE (ID = Results.ID) 
        FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')
      ,1,2,'') AS NameValues
    FROM #YourTable Results
    GROUP BY ID
    
    DROP TABLE #YourTable
    
    0 讨论(0)
  • 2020-11-21 04:57

    Another option using Sql Server 2005 and above

    ---- test data
    declare @t table (OUTPUTID int, SCHME varchar(10), DESCR varchar(10))
    insert @t select 1125439       ,'CKT','Approved'
    insert @t select 1125439       ,'RENO','Approved'
    insert @t select 1134691       ,'CKT','Approved'
    insert @t select 1134691       ,'RENO','Approved'
    insert @t select 1134691       ,'pn','Approved'
    
    ---- actual query
    ;with cte(outputid,combined,rn)
    as
    (
      select outputid, SCHME + ' ('+DESCR+')', rn=ROW_NUMBER() over (PARTITION by outputid order by schme, descr)
      from @t
    )
    ,cte2(outputid,finalstatus,rn)
    as
    (
    select OUTPUTID, convert(varchar(max),combined), 1 from cte where rn=1
    union all
    select cte2.outputid, convert(varchar(max),cte2.finalstatus+', '+cte.combined), cte2.rn+1
    from cte2
    inner join cte on cte.OUTPUTID = cte2.outputid and cte.rn=cte2.rn+1
    )
    select outputid, MAX(finalstatus) from cte2 group by outputid
    
    0 讨论(0)
  • 2020-11-21 04:57

    You can improve performance significant the following way if group by contains mostly one item:

    SELECT 
      [ID],
    
    CASE WHEN MAX( [Name]) = MIN( [Name]) THEN 
    MAX( [Name]) NameValues
    ELSE
    
      STUFF((
        SELECT ', ' + [Name] + ':' + CAST([Value] AS VARCHAR(MAX)) 
        FROM #YourTable 
        WHERE (ID = Results.ID) 
        FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')
      ,1,2,'') AS NameValues
    
    END
    
    FROM #YourTable Results
    GROUP BY ID
    
    0 讨论(0)
  • 2020-11-21 04:58

    An example would be

    In Oracle you can use LISTAGG aggregate function.

    Original records

    name   type
    ------------
    name1  type1
    name2  type2
    name2  type3
    

    Sql

    SELECT name, LISTAGG(type, '; ') WITHIN GROUP(ORDER BY name)
    FROM table
    GROUP BY name
    

    Result in

    name   type
    ------------
    name1  type1
    name2  type2; type3
    
    0 讨论(0)
提交回复
热议问题