如何使用 GROUP BY 在 SQL Server 中连接字符串?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/273238/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use GROUP BY to concatenate strings in SQL Server?
提问by Eldila
How do I get:
如何得到:
id Name Value
1 A 4
1 B 8
2 C 9
to
到
id Column
1 A:4, B:8
2 C:9
回答by Kevin Fairchild
No CURSOR, WHILE loop, or User-Defined Function needed.
不需要 CURSOR、WHILE 循环或用户定义的函数。
Just need to be creative with FOR XML and PATH.
只需要对 FOR XML 和 PATH 发挥创意。
[Note: This solution only works on SQL 2005 and later. Original question didn't specify the version in use.]
[注意:此解决方案仅适用于 SQL 2005 及更高版本。原始问题没有指定使用的版本。]
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
回答by Kannan Kandasamy
If it is SQL Server 2017 or SQL Server Vnext, SQL Azure you can use string_agg as below:
如果是 SQL Server 2017 或 SQL Server Vnext, SQL Azure 你可以使用 string_agg 如下:
select id, string_agg(concat(name, ':', [value]), ', ')
from #YourTable
group by id
回答by Allen
using XML path will not perfectly concatenate as you might expect... it will replace "&" with "&" and will also mess with <" and ">
...maybe a few other things, not sure...but you can try this
使用 XML 路径不会像您预期的那样完美连接……它将用“&”替换“&” 并且还会弄乱<" and ">
......也许还有其他一些事情,不确定......但你可以试试这个
I came across a workaround for this... you need to replace:
我遇到了一个解决方法......你需要更换:
FOR XML PATH('')
)
with:
和:
FOR XML PATH(''),TYPE
).value('(./text())[1]','VARCHAR(MAX)')
...or NVARCHAR(MAX)
if thats what youre using.
...或者NVARCHAR(MAX)
如果那是你正在使用的。
why the hell doesn't SQL
have a concatenate aggregate function? this is a PITA.
为什么地狱没有SQL
连接聚合函数?这是一个皮塔饼。
回答by Jonathan Sayce
I ran into a couple of problems when I tried converting Kevin Fairchild's suggestion to work with strings containing spaces and special XML characters (&
, <
, >
) which were encoded.
当我尝试将 Kevin Fairchild 的建议转换为使用包含空格和特殊 XML 字符(&
, <
, >
)的字符串时,我遇到了一些问题。
The final version of my code (which doesn't answer the original question but may be useful to someone) looks like this:
我的代码的最终版本(它没有回答原始问题,但可能对某人有用)如下所示:
CREATE TABLE #YourTable ([ID] INT, [Name] VARCHAR(MAX), [Value] INT)
INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (1,'Oranges & Lemons',4)
INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (1,'1 < 2',8)
INSERT INTO #YourTable ([ID],[Name],[Value]) VALUES (2,'C',9)
SELECT [ID],
STUFF((
SELECT ', ' + CAST([Name] AS VARCHAR(MAX))
FROM #YourTable WHERE (ID = Results.ID)
FOR XML PATH(''),TYPE
/* Use .value to uncomment XML entities e.g. > < etc*/
).value('.','VARCHAR(MAX)')
,1,2,'') as NameValues
FROM #YourTable Results
GROUP BY ID
DROP TABLE #YourTable
Rather than using a space as a delimiter and replacing all the spaces with commas, it just pre-pends a comma and space to each value then uses STUFF
to remove the first two characters.
它不是使用空格作为分隔符并用逗号替换所有空格,而是在每个值前添加一个逗号和空格,然后用于STUFF
删除前两个字符。
The XML encoding is taken care of automatically by using the TYPEdirective.
XML 编码是通过使用TYPE指令自动处理的。
回答by cyberkiwi
Another option using Sql Server 2005 and above
使用 Sql Server 2005 及更高版本的另一种选择
---- 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
回答by Orlando Colamatteo
Install the SQLCLR Aggregates from http://groupconcat.codeplex.com
从http://groupconcat.codeplex.com安装 SQLCLR 聚合
Then you can write code like this to get the result you asked for:
然后你可以写这样的代码来得到你要求的结果:
CREATE TABLE foo
(
id INT,
name CHAR(1),
Value CHAR(1)
);
INSERT INTO dbo.foo
(id, name, Value)
VALUES (1, 'A', '4'),
(1, 'B', '8'),
(2, 'C', '9');
SELECT id,
dbo.GROUP_CONCAT(name + ':' + Value) AS [Column]
FROM dbo.foo
GROUP BY id;
回答by Shem Sargent
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.
八年后... Microsoft SQL Server vNext 数据库引擎终于增强了 Transact-SQL 以直接支持分组字符串连接。Community Technical Preview 1.0 版添加了 STRING_AGG 函数,CTP 1.1 为 STRING_AGG 函数添加了 WITHIN GROUP 子句。
Reference: https://msdn.microsoft.com/en-us/library/mt775028.aspx
回答by Joel Coehoorn
SQL Server 2005 and later allow you to create your own custom aggregate functions, including for things like concatenation- see the sample at the bottom of the linked article.
SQL Server 2005 及更高版本允许您创建自己的自定义聚合函数,包括诸如连接之类的事情 - 请参阅链接文章底部的示例。
回答by Phillip
This is just an addition to Kevin Fairchild's post (very clever by the way). I would have added it as a comment, but I don't have enough points yet :)
这只是对 Kevin Fairchild 帖子的补充(顺便说一下,这很聪明)。我会把它添加为评论,但我还没有足够的分数:)
I was using this idea for a view I was working on, however the items I was concatinating contained spaces. So I modified the code slightly to not use spaces as delimiters.
我将这个想法用于我正在处理的视图,但是我连接的项目包含空间。所以我稍微修改了代码,不使用空格作为分隔符。
Again thanks for the cool workaround Kevin!
再次感谢凯文的酷解决方法!
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],
REPLACE(REPLACE(REPLACE(
(SELECT [Name] + ':' + CAST([Value] AS VARCHAR(MAX)) as A
FROM #YourTable
WHERE ( ID = Results.ID )
FOR XML PATH (''))
, '</A><A>', ', ')
,'<A>','')
,'</A>','') AS NameValues
FROM #YourTable Results
GROUP BY ID
DROP TABLE #YourTable
回答by Michal B.
An example would be
一个例子是
In Oracle you can use LISTAGG aggregate function.
在 Oracle 中,您可以使用 LISTAGG 聚合函数。
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