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

LINQ编写带DISTINCT、WHERE、ORDER BY的SQL等效查询方法

问题根因

之前两种写法丢数据的核心原因有两点:

  • 过滤条件顺序错误:Where(x => x.custid == UserId)放在了分组、取组内第一条之后执行。对应SQL逻辑是先对全表做分组取数,再筛选用户ID,和原SQL先过滤custid再去重的逻辑完全相反,必然丢数。
  • 去重逻辑绕路:用GroupBy().Select(x=>x.FirstOrDefault())本质是随机取分组内第一条完整记录,既无法保证取到的记录属于目标用户,也不是多字段DISTINCT的标准实现。C#匿名类型默认支持按所有属性做值相等判断,直接投影后调用Distinct()就能实现和SQL多字段DISTINCT完全一致的效果,不需要依赖DistinctBy扩展方法。
可直接运行的正确代码

代码执行顺序和原SQL完全对齐:先过滤目标用户数据,再做字段投影,再去重,最后排序。考虑到你的Razor视图需要加载Program、sample、Machine、sys_users等关联导航属性,建议先拿到去重的联合键,再关联查询完整实体,避免分组取首条导致的随机数据丢失:

public ActionResult Indexs()
{
    int UserId = Convert.ToInt32(Session["UserID"]);
    // 第一步:对齐SQL逻辑,拿到去重后的(machine_id, sample_id)联合键
    var distinctKeys = _context.RESULTS
        .Where(r => r.custid == UserId)
        .Select(r => new { r.machine_id, r.sample_id })
        .Distinct()
        .OrderBy(r => r.sample_id)
        .ToList();

    // 第二步:根据去重后的联合键,查询完整实体+关联表数据,供视图渲染
    var samples = _context.RESULTS
        .Include(r => r.Program)
        .Include(r => r.sample)
        .Include(r => r.Machine)
        .Include(r => r.sys_users)
        .Where(r => distinctKeys.Contains(new { r.machine_id, r.sample_id }))
        .OrderBy(r => r.sample_id)
        .ToList();

    return View(samples);
}
之前复合分组写法仅返回4条记录的原因

你之前写的复合分组代码执行顺序是:全表按(machine_id, sample_id)分组→每组随机取第一条记录→按sample_id、program_id排序→最后过滤custid等于当前用户的记录。
全表分组阶段,每个(machine_id, sample_id)组里可能混了多个custid的记录,FirstOrDefault()取到的大概率不是当前用户的记录,最后过滤时这些组就会被排除,只剩4个组刚好第一条记录属于当前用户,自然返回数据不全。

提示:用ORM写LINQ时尽量和SQL原生执行顺序对齐:先写Where过滤条件缩小数据范围,再做投影、去重、分组,最后写排序、分页逻辑,既不会出现逻辑错误,也能生成性能更好的SQL。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 04:48:15