C# LINQ如何筛选指定日期范围内未付款的客户记录
LINQ实现日期区间未付款客户筛选方案
LINQ 没有和SQL完全对应的NOT IN关键字,但可以通过非常简单的逻辑调整实现你要的反向筛选需求,两种常用实现方式如下:
方式一:直接反转判断条件(优先推荐)
你现有的已付款筛选逻辑是判断last_payment_date落在[startdate, enddate)区间内,未付款只需要对这个区间判断取反即可,不需要额外做集合对比,性能最高:
// 预先转换起止日期,避免循环内重复转换 DateTime rangeStart = Convert.ToDateTime(startdate); DateTime rangeEnd = Convert.ToDateTime(enddate); var unpaidList = paymentData .Where(v => v.district != null && !(Convert.ToDateTime(v.last_payment_date) >= rangeStart && Convert.ToDateTime(v.last_payment_date) < rangeEnd) ).ToList();
如果你的业务定义里,
last_payment_date为空也算未付款,只需要把条件补充为v.last_payment_date == null || !(上述区间判断)即可。
方式二:模拟SQL NOT IN 逻辑
如果你需要保留已付款客户列表做其他用途,可以通过主键排除的方式实现和NOT IN完全一致的效果:
DateTime rangeStart = Convert.ToDateTime(startdate); DateTime rangeEnd = Convert.ToDateTime(enddate); // 先取出区间内已付款客户的唯一标识集合 var paidCustomerIds = paymentData .Where(v => v.district != null && Convert.ToDateTime(v.last_payment_date) >= rangeStart && Convert.ToDateTime(v.last_payment_date) < rangeEnd) .Select(v => v.Id) // 替换为你实体中客户的唯一主键字段 .ToHashSet(); // 排除已付款客户,得到未付款列表 var unpaidList = paymentData .Where(v => v.district != null && !paidCustomerIds.Contains(v.Id)) .ToList();
注意这里用ToHashSet()而不是ToList()存已付款ID,是因为HashSet的包含判断时间复杂度是O(1),数据量大的时候性能比List的O(n)高很多。
优化提示
你当前的写法在每次循环条目时都会重复转换起止日期、重复转换last_payment_date字段,既存在日期格式不一致导致转换失败的风险,也有不必要的性能损耗,建议查询前先统一完成日期格式转换,再做条件判断。
内容的提问来源于stack exchange,提问作者Anikwenwa Tosan
相关产品推荐
相关产品推荐

