Я прокрутил свой собственный ответ на этот вопрос, и я не вижу в нем обратной стороны, однако я буду рад, если кто-нибудь на это скажет.
Что мне нравится, так это то, как я точно знаю, какие строкиобновление.
declare @MyItem table(
id int not null primary key,
amount money not null,
is_paid bit not null,
client varchar(10) not null)
insert into @MyItem values
(1, 9.50, 0, 'Client A'),
(2, 11.50, 0, 'Client A'),
(3, 20.00, 1, 'Client B')
select dbo.SumKeys(id) as [IDs], sum(amount) as total_amount, is_paid, client
from @MyItem
group by is_paid, client
![enter image description here](https://i.stack.imgur.com/Tsl5H.png)
Что мне не нравится, так это то, что мне понадобилось более полдня, чтобы заставить этот код работать, потому что я боролся (со мной)странности, которые связаны с программированием на сервере sql, размещенном на сервере.
В любом случае я создал агрегат, который помещает список идентификаторов, разделенных запятыми, прямо в мой запрос.
using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedAggregate(
Format.UserDefined,
IsInvariantToDuplicates = true,
IsInvariantToNulls = true,
MaxByteSize = -1
)]
public struct SumKeys : IBinarySerialize
{
private readonly static char sep = ',';
private SqlString result;
public void Init()
{
result = string.Empty;
}
public void Accumulate(SqlInt32 value)
{
if (!value.IsNull && !Contains(value))
this.Add(value);
}
private void Add(SqlInt32 value)
{
this.result += Wrap(value);
}
private void Add(string value)
{
Add(Convert.ToInt32(value));
}
private static string Wrap(SqlInt32 value)
{
return value.Value.ToString() + sep;
}
private bool Contains(SqlInt32 value)
{
return this.result.Value.Contains(Wrap(value));
}
public void Merge(SumKeys group)
{
foreach (var value in Items(group))
if (!this.Contains(value))
this.Add(value);
}
private static IEnumerable<SqlInt32> Items(SumKeys group)
{
foreach (var value in group.result.Value.Split(sep))
{
int i;
if (Int32.TryParse(value, out i))
yield return i;
}
}
public SqlString Terminate()
{
return this.result.Value.TrimEnd(sep);
}
public void Read(System.IO.BinaryReader r)
{
this.result = r.ReadString();
}
public void Write(System.IO.BinaryWriter w)
{
w.Write(this.result.Value.TrimEnd(sep));
}
}