我正在尝试在 SQL Server 端使用
STRING_AGG
。根据文档,从 EF Core 7.0 开始,
string.Join(separator, group.Select(x => x.Property))
应该翻译成
STRING_AGG(Property, @separator)
,但这个翻译没有发生。
我在这里缺少什么?
这是我的代码:
var names = _context.Account
.Select(l => new
{
Names = string.Join(" | ", l.Customers.Select(x=>x.FirstName))
}).ToListAsync();
但是,被翻译成这个查询
SELECT
[t].[AccountId], [c].[FirstName], [c].[CustomerID]
FROM
( FROM [Accounts] AS [l]
) AS [t]
LEFT JOIN
[Customer] AS [c] ON [t].[AccountId]= [c].[AccountId]
虽然我期待看到
SELECT
STRING_AGG([c].[FirstName], N' | ')
FROM
[Customer] AS [c]
WHERE
[l].[AccountId] = [c].[AccountId]) AS [Names]
FROM [Accounts] AS [l]
看起来
STRING_AGG
被设计为用作分组查询的一部分。这就是它在 EF Core 中的实现方式。但是,我们可以通过使用常量键进行分组来模仿此功能。例如:
EF Core 中的以下查询会生成
STRING_AGG
SQL,但生成的 SQL 可能看起来有问题:
var query = _context.Accounts
.SelectMany(a => a.Customers)
.GroupBy(c => 1) // Grouping by a constant
.Select(g => new
{
Names = string.Join(", ", g.Select(c => c.FirstName))
});
生成的SQL:
SELECT COALESCE(STRING_AGG([t].[FirstName], N', '), N'') AS [Names]
FROM (
SELECT [c].[FirstName], 1 AS [Key]
FROM [Accounts] AS [a]
INNER JOIN [Customers] AS [c] ON [a].[Id] = [c].[AccountId]
) AS [t]
GROUP BY [t].[Key]
虽然这种方法有效,但通过使用有意义的非常量键进行分组可以获得更好的结果。例如:
var query = _context.Accounts
.SelectMany(a => a.Customers)
.GroupBy(c => c.AccountId) // Grouping by AccountId
.Select(g => new
{
Names = string.Join(", ", g.Select(c => c.FirstName))
});
生成的SQL:
SELECT COALESCE(STRING_AGG([c].[FirstName], N', '), N'') AS [Names]
FROM [Accounts] AS [a]
INNER JOIN [Customers] AS [c] ON [a].[Id] = [c].[AccountId]
GROUP BY [c].[AccountId]