将SQL多表关联分组统计查询转换为EF LINQ查询的疑问
将SQL多表分组统计转换为EF LINQ查询
我来帮你搞定这个转换问题!结合你给出的实体类、ViewModel以及原始SQL逻辑,我整理了两种可行的LINQ实现方案,你可以根据自己的编码习惯选择:
方案一:利用实体导航属性(推荐)
你的实体类已经定义了完整的关联导航关系(Company包含offices集合,Office包含employees集合),用导航属性写LINQ会更简洁,也更符合EF的设计思路:
// 与原始SQL的INNER JOIN逻辑完全一致:仅返回有办公点且办公点存在员工的公司 var viewModel = _context.Companies // 过滤掉无办公点或办公点无员工的公司 .Where(c => c.offices.Any(o => o.employees.Any())) .Select(c => new MyViewModel { company = c, // 统计唯一员工数:展开所有办公点的员工,提取ID去重后计数 employeeCount = c.offices.SelectMany(o => o.employees) .Select(e => e.id) .Distinct() .Count(), // 统计办公点数量:直接取当前公司的办公点总数(天然唯一,无需额外去重) officeCount = c.offices.Count() }) .ToList();
如果不需要过滤(想返回所有公司,无办公点/员工的计数自动为0),直接去掉Where条件即可。
方案二:显式Join写法(贴近原始SQL)
如果你更习惯SQL的Join语法,可以用这种方式,核心是先完成多表关联,再按公司分组统计:
var viewModel = from c in _context.Companies join o in _context.Offices on c.id equals o.companyId join e in _context.Employees on o.id equals e.officeId // 按公司对象分组,将关联的办公点、员工打包到分组集合中 group new { c, o, e } by c into grouped select new MyViewModel { company = grouped.Key, // 提取分组内所有员工ID,去重后计数 employeeCount = grouped.Select(g => g.e.id).Distinct().Count(), // 提取分组内所有办公点ID,去重后计数 officeCount = grouped.Select(g => g.o.id).Distinct().Count() };
关键逻辑对应说明:
- SQL中的
COUNT(DISTINCT 字段)对应LINQ的Select(字段).Distinct().Count(),先提取目标字段去重,再统计数量。 - SQL中的
GROUP BY Company.name在LINQ中通过group ... by c实现(因为Company的id是唯一标识,按整个公司对象分组等价于按name分组,同时能完整保留公司实体信息)。
内容的提问来源于stack exchange,提问作者aatosm
相关产品推荐
相关产品推荐

