【问题标题】:Optimizing queries in Entity Framework Core / LINQ for group by / count()在 Entity Framework Core / LINQ 中为 group by / count() 优化查询
【发布时间】:2020-08-23 02:33:32
【问题描述】:

我一直在尝试使用 Entity Framework Core 和 LINQ 编写查询的不同方法,包括“group by”和“count()”。但是生成的 SQL 只是简单地返回所有记录,然后“group by”和“count()”在内存中完成。

目前我正在尝试编写一个等效于以下 SQL 的查询:

select 
    e.EngagementId,
    e.Name,
    c.ClientName,
    count(distinct ed.EngagementDocumentId) as DocumentCount,
    count(distinct es.EngagementSurveyId) as SurveyCount
from Engagement e
inner join Client c on c.ClientId = e.ClientId
left outer join EngagementDocument ed on ed.EngagementId = e.EngagementId
left outer join EngagementSurvey es on es.EngagementId = e.EngagementId
group by e.EngagementId, e.Name, c.ClientName

我的问题是:如何编写生成类似 SQL 的查询?

【问题讨论】:

  • 你使用的是哪个 EF Core 版本?
  • 我使用的是 2.2.4 版本
  • 谢谢!我会看看的。但我的问题并不特别是“计数不同”。通常,所有使用“分组依据”的查询似乎都在内存中处理。我只是使用了上面的示例,因为如果我能解决这个问题,那么我也可以使用“group by”来解决更简单的查询。
  • 如果在GroupBy 之后添加Select 仅带有键/聚合,则查询应转换为SQL。

标签: sql .net linq entity-framework-core ef-core-2.2


【解决方案1】:

我会推荐相关子查询或(等效地)横向连接:

select e.EngagementId, e.Name, c.ClientName,
       (select count(*)
        from EngagementDocument ed 
        where ed.EngagementId = e.EngagementId,
       ) as DocumentCount,
       (select count(*)
        from EngagementSurvey es 
        where es.EngagementId = e.EngagementId,
       ) as SurveyCount
from Engagement e inner join
     Client c 
     on c.ClientId = e.ClientId;

此外,您希望在 EngagementDocument(EngagementId)EngagementSurvey(EngagementId) 上建立索引。

您的版本正在为每个客户/参与创建文档和调查的笛卡尔积 - 然后使用额外的资源来汇总和删除重复项。以上可以通过扫描索引来进行计数。

【讨论】:

  • 有趣!我的印象是使用连接和“分组依据”比使用子查询获得更好的性能?!通常应该避免子查询。无论如何,这将如何转换为 EF / LINQ?
猜你喜欢
  • 2020-05-17
  • 2010-09-23
  • 2015-08-08
  • 2012-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-18
相关资源
最近更新 更多