LINQ(到Oracle) - Row_Number()Over Partition By

时间:2013-03-08 16:57:33

标签: sql-server linq oracle entity-framework

这可能是其他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代码非常相似(如果不相同)。

2 个答案:

答案 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
相关问题