这是对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解决方案将是理想的。
答案 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)。
您可以尝试将所有结果下拉到应用程序中并在那里执行行号。这可能会伤害或有益于性能。它取决于具体情况。