【问题标题】:Efficient query for only the first N rows for each unique ID高效查询每个唯一 ID 的前 N ​​行
【发布时间】:2013-09-11 14:17:55
【问题描述】:

这是this问题的后续。

TLDR:

问题:

我想过滤一个查询,只保留每个唯一 ID 的前 n 行。

答案:

query = query.GroupBy(q => q.ID).SelectMany(g => g.Take(n));

这个答案的问题在于,对于超过 80,000 行,评估查询比通过迭代过滤 (foreach) 花费的时间要长得多(至少慢两倍)。查看此答案生成的 SQL,使用了 CROSS APPLY,最有可能用于 SelectMany()

This link 描述了CROSS APPLY 的作用:

APPLY 运算符允许您连接两个表表达式;每次从左表表达式开始,每行都会处理右表表达式。

简而言之,我正在寻找一个过滤查询,它可以有效地为每个唯一的 ID 收集顶部的 N 行。

具有解释性 SQL 的 Linq 解决方案将是理想的。

【问题讨论】:

  • 另一种实现最大 n 每组查询的常用方法是 ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Y) 然后对其进行过滤。不确定 linq-to-sql 是否可以生成该 SQL。
  • 当然这种过滤方式比不使用过滤需要更多calculations,所以效率下降是可以理解的。
  • 编辑了我的问题。很抱歉造成混乱。

标签: c# sql linq linq-to-sql


【解决方案1】:

我在 SQL here(底部的 SQL 2000 解决方案)中找到了我的答案,并设法实现了 Queryable/Linq 版本:

query = tableQueryable.Where(a =>
          tableQueryable.Where(b => b.ID == a.ID)
            .OrderByDescending(o => o.Timestamp)
            .Take(N)
            .Select(s => s.PK)
          .Contains(a.PK)
        ).OrderByDescending(d => d.Timestamp);

相当标准的“子查询”模式。在大桌子上速度要快得多。

【讨论】:

    【解决方案2】:

    L2S 没有行号,因此无法使用 Martin 的技巧。我也遇到过这个问题,据我所知,这是最佳的 L2S 解决方案(不以任何方式使用原生 SQL)。

    您可以尝试将所有结果拉入应用程序并在那里执行行号操作。这可能会损害或有利于性能。具体是哪一种,要看具体情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-08
      • 2015-10-28
      • 2022-11-15
      • 2021-06-25
      • 2017-02-03
      • 2021-06-02
      • 2011-09-05
      • 1970-01-01
      相关资源
      最近更新 更多