Gur*_*der 22 asp-classic sql-server-2008
如果有一个名为employee的表
EmpID EmpName
---------- -------------
1 Mary
1 John
1 Sam
2 Alaina
2 Edward
Run Code Online (Sandbox Code Playgroud)
结果我需要这种格式:
EmpID EmpName
---------- -------------
1 Mary, John, Sam
2 Alaina, Edward
Run Code Online (Sandbox Code Playgroud)
问:这条记录在同Employee
一张表中.我几乎没有使用UDF,存储过程的经验,我需要通过查询完成这个事情.这可能不使用UDF,SP.
Ole*_*Dok 31
#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
Run Code Online (Sandbox Code Playgroud)
如何剥离最终的逗号 - 是你自己的
CLR聚合#2的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
}
}
Run Code Online (Sandbox Code Playgroud)
t-c*_*.dk 13
来自@ OlegDok的所选答案可能会返回正确的结果.但表现可能很糟糕.这个测试场景将说明它.
创建临时表:
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
Run Code Online (Sandbox Code Playgroud)
这只有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
Run Code Online (Sandbox Code Playgroud)
在这种情况下,区别不是清理行的正确方法.要避免此笛卡尔联接,请在加入之前减少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
Run Code Online (Sandbox Code Playgroud)
这需要不到1秒钟
归档时间: |
|
查看次数: |
34159 次 |
最近记录: |