You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在EF Core中单次查询获取分组数量及总值?

EF Core实现单次查询获取分组计数与总值

先看数据表结构:

id   internal_id  external_id  value
---  -----------  -----------  -----
1    1            null         5
2    1            null         3
3    null         2            8
4    null         2            3
5    3            null         2
6    null         4            9

需求是按(internal_id, external_id)分组,获取分组总数(此处为4)以及所有分组的value总和(此处为30),对应的PostgreSQL原生SQL用CTE实现如下:

WITH t AS (
  SELECT sum(value) val FROM phones
  GROUP BY internal_id, external_id
)
SELECT count(*), sum(val) FROM t;

你当前的做法是把所有分组的value总和拉到客户端再计算总数和总和,确实会浪费网络带宽,完全可以通过EF Core的Linq查询让数据库直接返回这两个结果,只需要一次查询:

var stats = await _Phones
    // 按目标字段分组,计算每个分组的value总和
    .GroupBy(x => new { x.InternalId, x.ExternalId })
    .Select(g => g.Sum(x => x.Value))
    // 将每个分组的总和转为包含计数标识的结构
    .Select(val => new { GroupCount = 1, GroupSum = val })
    // 按固定值分组,实现全局聚合
    .GroupBy(_ => 1)
    // 计算最终的分组总数和总value和
    .Select(g => new {
        TotalGroupCount = g.Count(),
        TotalValueSum = g.Sum(x => x.GroupSum)
    })
    .FirstOrDefaultAsync();

int groupCount = stats.TotalGroupCount;
decimal totalValue = stats.TotalValueSum;

这段Linq查询会被EF Core转换为和你提供的CTE逻辑一致的SQL,所有计算都在数据库端完成,最终只返回两个数值,避免了传输大量中间数据。

如果更倾向于使用原生SQL(比如担心Linq的转换问题),也可以直接用FromSqlRaw执行你写的SQL语句:

// 注意:若使用无实体查询,需确保EF Core版本支持,或临时映射到实体字段
var stats = await _context.Database
    .SqlQuery<StatsResult>(@"
        WITH t AS (
          SELECT sum(value) val FROM phones
          GROUP BY internal_id, external_id
        )
        SELECT count(*) as TotalGroupCount, sum(val) as TotalValueSum FROM t;
    ")
    .FirstOrDefaultAsync();

// 需定义对应的结果类
public class StatsResult
{
    public int TotalGroupCount { get; set; }
    public decimal TotalValueSum { get; set; }
}

更推荐使用Linq写法,它能更好地适配EF Core的上下文和类型安全。

内容的提问来源于stack exchange,提问作者egeo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 21:45:33