这可能是其他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中包含最高值的行。将顺序更改为asc当然会返回最低值或将等级更改为2将获得第二高/最低值等等。有没有办法编写可以执行服务器端的LINQ查询给我们同样的功能?理想情况下,与上述一样有效。
修改
在浏览网页后我尝试了很多不同的解决方案,他们最终都给了我同样的问题,下面是里德的回答,因为生成的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);
这两者导致使用Oracle不支持的OUTER APPLY
的SQL代码非常相似(如果不相同)。
答案 0 :(得分:5)
您应该可以执行以下操作:
var results = someTable
.GroupBy(row => row.id)
.Select(group => group.OrderByDescending(r => r.id).First());
如果你想要第三个最高值,你可以这样做:
var results = someTable
.GroupBy(row => row.id)
.Select(group => group.OrderByDescending(r => r.id).Skip(2).FirstOrDefault())
.Where(r => r != null); // Remove the groups that don't have 3 items
答案 1 :(得分:1)
另一种方法,使用子查询,为每个field1
单独获取最大ID
。
SELECT a.*
FROM someTable a
INNER JOIN
(
SELECT id, max(field1) max_field
FROM sometable
GROUP BY id
) b ON a.id = b.ID AND
a.field1 = b.max_field
转换为LINQ
时:
from a in someTable
join b in
(
from o in someTable
group o by new {o.ID} into g
select new
{
g.Key.ID,
max_field = g.Max(p => p.field1)
}
) on new {a.ID, a.field1} equals new {b.ID, field1 = b.max_field}
select a