2

这可能是其他 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 查询,这给了我们相同的功能?理想情况下,性能与上述一样。

编辑: 我在网上搜索后尝试了许多不同的解决方案,它们最终都给了我同样的问题,因为生成的 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);

这两者都导致使用OUTER APPLYOracle 不支持的 SQL 代码(如果不相同的话)非常相似。

4

2 回答 2

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
于 2013-03-08T17:02:46.687 回答
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
于 2013-03-08T17:05:14.777 回答