【发布时间】:2013-02-24 07:27:23
【问题描述】:
这可能与其他 Partition By + Rank 问题重复,但我发现这些问题/答案中的大多数都过于特定于其特定的业务逻辑。我正在寻找的是以下类型查询的更通用的 LINQ 版本:
SELECT id,
field1,
field2,
ROW_NUMBER() OVER (PARTITION BY id
ORDER BY field1 desc) ROWNUM
FROM someTable;
我们对此做的一个非常常见的事情是把它包装成这样的东西:
SELECT id,
field1,
field2
FROM (SELECT id,
field1,
field2,
ROW_NUMBER() OVER (PARTITION BY id
ORDER BY field1 desc) ROWNUM
FROM someTable)
WHERE ROWNUM = 1;
它返回包含每个 id 的 field1 中的最大值的行。将 order by 更改为 asc 当然会返回最小值或将等级更改为 2 将获得第二高/最低值等,等等。有没有办法编写一个可以在服务器端执行的 LINQ 查询,这给了我们相同的功能?理想情况下,性能与上述一样。
编辑:
在搜索网络后,我尝试了许多不同的解决方案,它们最终都给了我与 Reed 下面的答案相同的问题,因为生成的 SQL 包含一个APPLY。
我试过的几个例子:
from p in db.someTable
group p by p.id into g
let mostRecent = g.OrderByDescending(o => o.field1).FirstOrDefault()
select new {
g.Key,
mostRecent
};
db.someTable
.GroupBy(g => g.id, (a, b) => b.OrderByDescending(o => o.field1).Take(1))
.SelectMany(m => m);
这两种方法都会导致非常相似(如果不相同)的 SQL 代码使用 Oracle 不支持的 OUTER APPLY。
【问题讨论】:
-
对我来说,这似乎是一个简单的 GROUP BY
id和MAX(field1)。我错过了什么吗? -
@FrancisP 以目前的形式,是的。但是如果我不想要 MAX 而想要第二个或第三个呢?我已经删除了对那个特定部分的强调。
-
@Kittoes 同样的技术应该可以通过添加一个
Skip调用然后过滤掉任何空结果......
标签: sql-server linq oracle entity-framework