SQL转Lambda-LINQ求助:统计查询语句迁移问题
解决SQL转EF LINQ Lambda的问题
首先先明确你原SQL的核心逻辑:
从
ProcessTable中筛选出InstanceID匹配指定值、ProcessType匹配指定值且ProcessStatus为3(已完成)的数据,按ProcessType分组后,统计每组的记录数(COUNT([ProcessID])),以及计算每组中EndDate与StartDate的时间差的平均值(以秒为单位)。
接下来看看你现有代码里的几个问题:
- 拼写错误:
ProcesoStatusEquals应该是p.ProcessStatus.Equals;StarDate是笔误,应该是StartDate;ProcesType应该是ProcessType Count的用法错误:tp.Count(tp.ProcessID)不符合LINQ语法,应该用tp.Count(p => p.ProcessID != null)(和原SQL的COUNT([ProcessID])逻辑一致,排除ProcessID为空的记录),如果ProcessID是主键不会为空,直接用tp.Count()也可以- 时间差计算错误:原SQL用
DATEDIFF(s, StartDate, EndDate)得到秒数,而EF中DateTime相减得到TimeSpan,需要用TotalSeconds获取总秒数后再计算平均值
正确的LINQ查询语法写法
var result = from p in ctx.ProcessTable where p.InstanceID.Equals(instanceID) // 注意和你的实体类字段名对应,原代码写的ProcessInstanceID请自行调整 && p.ProcessType.Equals(processType) && p.ProcessStatus.Equals(ProcessStatusEnum.FINISHED) // 假设该枚举值对应SQL中的3 group p by p.ProcessType into tp select new { Count = tp.Count(p => p.ProcessID != null), AverageDuration = tp.Average(p => (p.EndDate - p.StartDate).TotalSeconds), ProcessType = tp.Key // 分组的键就是ProcessType };
对应的Lambda方法语法写法
var result = ctx.ProcessTable .Where(p => p.InstanceID.Equals(instanceID) && p.ProcessType.Equals(processType) && p.ProcessStatus.Equals(ProcessStatusEnum.FINISHED)) .GroupBy(p => p.ProcessType) .Select(tp => new { Count = tp.Count(p => p.ProcessID != null), AverageDuration = tp.Average(p => (p.EndDate - p.StartDate).TotalSeconds), ProcessType = tp.Key });
关键部分解释
- Count逻辑匹配:原SQL的
COUNT([ProcessID])会忽略ProcessID为null的记录,tp.Count(p => p.ProcessID != null)和它完全对齐;如果ProcessID是不可为空的主键,直接用tp.Count()即可。 - 平均耗时转换:
p.EndDate - p.StartDate得到TimeSpan类型,TotalSeconds返回该时间间隔的总秒数(支持小数),和SQL的DATEDIFF(s, ...)逻辑一致;如果需要整数秒的平均值,可以用(int)(p.EndDate - p.StartDate).TotalSeconds再取平均。 - 分组键的获取:分组后
tp.Key就是你指定的分组依据ProcessType,不需要额外取值。
内容的提问来源于stack exchange,提问作者NioZero
相关产品推荐
相关产品推荐

