C# 如何对记录进行分组并仅检索前N个记录的第一个组
我有以下记录C# 如何对记录进行分组并仅检索前N个记录的第一个组,c#,entity-framework,linq,entity-framework-core,ef-core-2.0,C#,Entity Framework,Linq,Entity Framework Core,Ef Core 2.0,我有以下记录 ID BatchID ClientName CreatedDateTime ----------- -------------- --------------- ----------------------- 1 NULL B 2018-02-16 19:07:46.320 2 NULL B 2018-02-1
ID BatchID ClientName CreatedDateTime
----------- -------------- --------------- -----------------------
1 NULL B 2018-02-16 19:07:46.320
2 NULL B 2018-02-16 19:07:46.320
3 NULL B 2018-02-16 19:07:46.597
4 NULL B 2018-02-16 19:07:46.597
5 NULL B 2018-02-16 19:10:10.260
6 NULL B 2018-02-16 19:10:10.260
7 NULL B 2018-02-16 19:21:34.303
8 NULL B 2018-02-16 19:21:34.303
9 NULL B 2018-02-16 19:21:44.780
10 NULL B 2018-02-16 19:21:44.780
11 NULL A 2018-02-16 19:24:35.623
12 NULL A 2018-02-16 19:24:35.623
13 NULL A 2018-02-16 19:24:42.867
14 NULL A 2018-02-16 19:24:42.867
我在efcore中使用linqtosql
我想过滤BatchID
为NULL
的记录,然后按CreatedDateTime
对过滤后的记录进行排序,然后按ClientName
对它们进行分组,然后从第一个组中选取前5个记录
基于上面给定的记录集,它应该返回ClientNameB
id为1,2,3,4,5的记录
这是我的问题
var result = await _DBContext.BatchRequests
.Where(x => x.BatchID.HasValue == false)
.OrderBy(x => x.CreatedDateTime)
.GroupBy(x => x.ClientName)
.FirstAsync();
问题1> 查询返回客户端
A
2> 我如何只录制前5张唱片 更新1 Sql事件探查器显示以下内容,它甚至不在Sql中分组
SELECT [x].[ID], [x].[BatchID], [x].[ClientName], [x].[CreatedDateTime]
FROM [BatchRequests] AS [x]
WHERE CASE
WHEN [x].[BatchID] IS NULL
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END <> 0
ORDER BY [x].[ClientName]
选择[x].[ID],[x].[BatchID],[x].[ClientName],[x].[CreatedDateTime]
从[BatchRequests]到[x]
在哪里
当[x].[BatchID]为空时
然后强制转换(1为位)否则强制转换(0为位)
结束0
订购人[x]。[ClientName]
您必须以如下方式投影组结果:
result = await _DBContext.BatchRequests
.Where(x => x.BatchID.HasValue == false)
.OrderBy(x => x.CreatedDateTime)
.ThenBy(x => x.ClientName)
.GroupBy(x => x.ClientName)
.Select( x => new { ClientName= x.ClientName,
TopFive = x.Take(5)
})
.FirstAsync();
首先,在将LINQ查询转换为SQL的
Queryable
实现中,如果后跟GroupBy
,则通常OrderBy
无效(被忽略)
其次,EF Core目前不将GroupBy
查询转换为SQL,而是在内存中处理它们(所谓的),这使得它们的效率非常低。考虑到这一点,您最好将工作分为两个查询—一个用于获取第一组的ClientName
,另一个用于获取所需的结果:
var baseQuery = _DBContext.BatchRequests
.Where(x => x.BatchId == null)
.OrderBy(x => x.CreatedDateTime);
var clientName = await baseQuery
.Select(x => x.ClientName)
.FirstOrDefaultAsync();
var result = await baseQuery
.Where(x => x.ClientName == clientName)
.Take(5)
.ToListAsync();
实际上,您可以将这两个查询组合起来,但我不确定这是否会更有效(可能更糟):
您的
OrderBy
在GroupBy
之后没有多大意义-您必须对组进行排序。那么,您希望如何对组进行排序?(同样,一个简单的x.BatchID==null
可能会产生更好的SQL。)仅供参考,EF Core与LINQ to SQL或EF6没有任何共同之处。例如,正如您已经注意到的,它当前没有将GroupBy
查询转换为SQL。检索内存中的所有记录并在内存中进行分组并只取前N有什么用。您将不得不等待EF Core 2.1。这是我认为EF Core还没有准备好投入生产的一个原因。它产生相同的结果并返回clientB
。事实上,SQL探查器显示的SQL与我在上面更新1中发布的查询的SQL完全相同。您确定这是生成的SQL吗?是的,正如有人指出的,当您使用group by时,order by不会产生任何影响
var baseQuery = _DBContext.BatchRequests
.Where(x => x.BatchId == null)
.OrderBy(x => x.CreatedDateTime);
var result = await baseQuery
.Where(x => x.ClientName == baseQuery.Select(y => y.ClientName).FirstOrDefault())
.Take(5)
.ToListAsync();