C# Linq在没有.GroupBy()的情况下获取不同的有序元素

C# Linq在没有.GroupBy()的情况下获取不同的有序元素,c#,linq,linq-to-entities,C#,Linq,Linq To Entities,给定数据库中具有以下值的IQueryable(值为假,以及实体和字段的名称): 我需要将此IQueryable转换为IOrderedQueryable,使用类别中最昂贵产品的值,按价格降序排序。所以它可能看起来像: Id | CategoryName | Price ------ | -------------|------- 5 | boat | 30000 7 | car | 15000 8 | food

给定数据库中具有以下值的IQueryable(值为假,以及实体和字段的名称):

我需要将此IQueryable转换为IOrderedQueryable,使用类别中最昂贵产品的值,按价格降序排序。所以它可能看起来像:

Id     | CategoryName | Price
------ | -------------|-------
5      | boat         | 30000
7      | car          | 15000
8      | food         | 200
由于IQueryable提供了在底层SQL查询中执行分组和排序的能力(而实际表包含大约10k行,其中包含关于如何分组以对值进行排序的更复杂标准),所以这里我想要的关键是性能

我已经有了一个可行的解决方案,如下所示:

IQueryable<Product> queryable = ...;
var result = queryable
    .GroupBy(
        x => x.CategoryName,
        (_, productsInGroup) => productsInGroup
            .FirstOrDefault(x => x.Price == productsInGroup.Max(p => p.Price))
    .OrderByDescending(x => x.Price);
这样,该查询将首先按降序对值进行排序:

Id     | CategoryName | Price
------ | -------------|-------
5      | boat         | 30000
3      | boat         | 20000
7      | car          | 15000
2      | boat         | 15000
1      | car          | 10000
4      | car          | 5000
8      | food         | 200
6      | food         | 100
然后以某种方式排除第3、2、1、4、6行,因为它们的CategoryName已经出现在上面的行中


如何做到这一点?

从我在帖子中的查询中可以看出: 首先查找组中的最大价格

productsInGroup.Max(p => p.Price)
然后查找具有匹配价格的第一个元素

FirstOrDefault(x => x.Price == productsInGroup.Max(p => p.Price))
不确定是否可以通过跳过分组,但在按价格订购后从组中获取第一个元素可能更简单

var result = Products.GroupBy(f => f.CategoryName).Select(gr => gr.OrderByDescending(p => p.Price).First() );

我想到的唯一替代方法是使用带比较条件的自反联接(或基于
的查询
不存在),如下所示:

var result = queryable
    .Where(x => !queryable.Any(y => y.CategoryName == x.CategoryName && y.Price > x.Price))
    .OrderByDescending(x => x.Price)
    .ToList();
它的性能是否更好取决于具体的可查询性和数据库表索引

值得一提的是,上述内容并不完全等同,因为如果每组有两个或多个元素具有最高价格,则每个类别将返回多个记录,因此完全等同的内容需要其他标准,如:

y => y.CategoryName == x.CategoryName &&
    (y.Price > x.Price || (y.Price == x.Price && y.Id > x.Id))

你对分组有什么问题?您的查询需要多长时间?您是否在SQL profiler中分析了查询并添加了合适的索引?10万行很小。如果需要,请将它们全部读入内存。由于这是linq to entities,您可能需要一个查询,该查询将转换为按类别排序的秩/行\u编号Price@Phil目前,执行分页查询需要1.5-2秒的时间(跳过一些行,再获取另一行)。示例中表示为Price的值由复杂规则使用其他几个表计算,CategoryName实际上是相关表中的一列。现在有一些索引,但老实说,我还没有使用SQL分析器。我想这可以提高性能。所以你的意思是,计算价格可能会扼杀你的性能。菲尔:好吧,我同意,这是正确的观点。但是,在这个例子中,也许还有一个避免GroupBy的选项?
var result = queryable
    .Where(x => !queryable.Any(y => y.CategoryName == x.CategoryName && y.Price > x.Price))
    .OrderByDescending(x => x.Price)
    .ToList();
y => y.CategoryName == x.CategoryName &&
    (y.Price > x.Price || (y.Price == x.Price && y.Id > x.Id))