SQL Server中的SQL group_concat函数[重复]
Posted
技术标签:
【中文标题】SQL Server中的SQL group_concat函数[重复]【英文标题】:SQL group_concat function in SQL Server [duplicate] 【发布时间】:2012-02-10 17:18:08 【问题描述】:如果有一个表叫employee
EmpID EmpName
---------- -------------
1 Mary
1 John
1 Sam
2 Alaina
2 Edward
我需要这种格式的结果:
EmpID EmpName
---------- -------------
1 Mary, John, Sam
2 Alaina, Edward
问:这条记录在同一个Employee
表中。我几乎没有使用UDF,存储过程的经验,我需要通过查询来完成这件事。不使用UDF,SP这可能吗?
【问题讨论】:
哪个 SQL Server 版本?你看***.com/questions/451415/… 我正在使用 sql server 2008 @ BartekR @OlegDok 因为我是 sql 新手,我已经尝试过该帖子,但我对其中的 column_names 感到困惑..:( 【参考方案1】:-
用于 XML 路径 trick 和 article
CLR 用户定义聚合
对于 sql server 2005 之前的版本 - 临时表
#1 的示例
DECLARE @t TABLE (EmpId INT, EmpName VARCHAR(100))
INSERT @t VALUES
(1, 'Mary'),(1, 'John'),(1, 'Sam'),(2, 'Alaina'),(2, 'Edward')
SELECT distinct
EmpId,
(
SELECT EmpName+','
FROM @t t2
WHERE t2.EmpId = t1.EmpId
FOR XML PATH('')
) Concatenated
FROM @t t1
如何去掉最后的逗号 - 是你自己的
#2 的 CLR 聚合 c# 代码
using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Text;
using Microsoft.SqlServer.Server;
using System.IO;
namespace DatabaseAssembly
[Serializable]
[SqlUserDefinedAggregate(Format.UserDefined,
IsInvariantToNulls = true,
IsInvariantToDuplicates = true,
IsInvariantToOrder = true,
MaxByteSize = -1)]
public struct StringJoin : IBinarySerialize
private Dictionary<string, string> AggregationList
get
if (_list == null)
_list = new Dictionary<string, string>();
return _list;
private Dictionary<string, string> _list;
public void Init()
public void Accumulate(SqlString Value)
if (!Value.IsNull)
AggregationList[Value.Value.ToLowerInvariant()] = Value.Value;
public void Merge(StringJoin Group)
foreach (var key in Group.AggregationList.Keys)
AggregationList[key] = Group.AggregationList[key];
public SqlChars Terminate()
var sb = new StringBuilder();
foreach (var value in AggregationList.Values)
sb.Append(value);
return new SqlChars(sb.ToString());
#region IBinarySerialize Members
public void Read(System.IO.BinaryReader r)
try
while (true)
AggregationList[r.ReadString()] = r.ReadString();
catch (EndOfStreamException)
public void Write(System.IO.BinaryWriter w)
foreach (var key in AggregationList.Keys)
w.Write(key);
w.Write(AggregationList[key]);
#endregion
【讨论】:
精湛的临时表工作...Thnx...:)..现在我必须努力排除最后一个逗号..【参考方案2】:@OlegDok's 选择的答案可能会返回正确的结果。但性能可能很糟糕。这个测试场景将说明它。
创建临时表:
CREATE table #temp (EmpId INT, EmpName VARCHAR(100))
;WITH N(N)AS
(SELECT 1 FROM(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1))M(N)),
tally(N)AS(SELECT ROW_NUMBER()OVER(ORDER BY N.N)FROM N,N a,N b,N c,N d,N e,N f)
INSERT #temp
SELECT EmpId, EmpName FROM (values(1, 'Mary'),(1, 'John'),(1, 'Sam')) x(EmpId, EmpName)
CROSS APPLY
(SELECT top 2000 N FROM tally) y
UNION ALL
SELECT EmpId, EmpName FROM (values(2, 'Alaina'),(2, 'Edward')) x(EmpId, EmpName)
CROSS APPLY
(SELECT top 2000 N FROM tally) y
这只有 10.000 行。但是有很多相同的 EmpId。
Oleg 的回答中的这个查询在我的数据库上花费了 64 秒。
SELECT distinct
EmpId,
(
SELECT EmpName+','
FROM #temp t2
WHERE t2.EmpId = t1.EmpId
FOR XML PATH('')
) Concatenated
FROM #temp t1
在这种情况下,Distinct 不是清理行的正确方法。 为避免这种笛卡尔连接,请在加入之前减少初始 ID 数量。
这是正确的处理方式:
;WITH CTE as
(
SELECT distinct EmpId
FROM #temp
)
SELECT
EmpId,
STUFF((
SELECT ','+EmpName
FROM #temp t2
WHERE t2.EmpId = t1.EmpId
FOR XML PATH('')
), 1,1,'') Concatenated
FROM CTE t1
这需要不到 1 秒
【讨论】:
【参考方案3】:我认为 MSSQL 中没有 GROUP_CONCAT
函数。这个article 展示了连接行值的不同方式。
当项目数量较少且预先已知时连接值
SELECT CategoryId,
MAX( CASE seq WHEN 1 THEN ProductName ELSE '' END ) + ', ' +
MAX( CASE seq WHEN 2 THEN ProductName ELSE '' END ) + ', ' +
MAX( CASE seq WHEN 3 THEN ProductName ELSE '' END ) + ', ' +
MAX( CASE seq WHEN 4 THEN ProductName ELSE '' END )
FROM ( SELECT p1.CategoryId, p1.ProductName,
( SELECT COUNT(*)
FROM Northwind.dbo.Products p2
WHERE p2.CategoryId = p1.CategoryId
AND p2.ProductName <= p1.ProductName )
FROM Northwind.dbo.Products p1 ) D ( CategoryId, ProductName, seq )
GROUP BY CategoryId ;
More ways on this link.
【讨论】:
【参考方案4】:这是开头给出的示例的解决方案:
SELECT DISTINCT emp_name,
STUFF(
(SELECT ', ' + RTRIM(proj_id)
FROM project_members AS t1
WHERE t1.emp_name = t2.emp_name
FOR XML PATH (''))
, 1, 1, '')
FROM project_members t2
【讨论】:
以上是关于SQL Server中的SQL group_concat函数[重复]的主要内容,如果未能解决你的问题,请参考以下文章
如何查看sql server 2008的SQL语句执行错误日志
使用 SQLBulkCopy - SQL Server 2016 中的表比 SQL Server 2014 中的表大得多
本地 SQL Server 实例和 Azure SQL Server 中的 LoadData 脚本
sqlserver之[SQL Server]缓冲池中的可用内存不足。[Microsoft][ODBC SQL Server Driver][SQL Server]语句已终止