高效查询每个唯一ID的前N行

时间:2013-09-11 14:17:55

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

这是对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运算符允许您连接两个表表达式;每次为左表表达式中的每一行处理右表表达式。

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

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

2 个答案:

答案 0 :(得分:2)

我在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);

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

答案 1 :(得分:1)

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

您可以尝试将所有结果下拉到应用程序中并在那里执行行号。这可能会伤害或有益于性能。它取决于具体情况。