gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-03 22:58:32 26 4
gpt4 key购买 nike

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

Id     | CategoryName | Price
------ | -------------|-------
1 | car | 10000
2 | boat | 15000
3 | boat | 20000
4 | car | 5000
5 | boat | 30000
6 | food | 100
7 | car | 15000
8 | food | 200

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

Id     | CategoryName | Price
------ | -------------|-------
5 | boat | 30000
7 | car | 15000
8 | food | 200

由于 IQueryable 提供了在底层 SQL 查询中执行分组和排序的能力(真正的表包含大约 10k 行,关于如何对值进行分组排序的标准更复杂),我想要的关键是 < em>性能。

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

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);

此解决方案导致使用 GROUP BY 和嵌套选择(计算 MAX(p.Price)、选择组中的正确行等)的长查询

没有 GroupBy 是否有能力做到这一点?我想要这样的东西:

var result = queryable
.OrderByDescending(x => x.Price)
.ExcludeRowsWithDuplicateCategoryName(); // Distinct by predicate

以便这样的查询将首先按降序对值进行排序:

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 已经出现在上面的行中。

我该怎么做?

最佳答案

我想到的唯一选择是使用带有比较条件(或基于NOT EXISTS 的查询)的self anti join,如下所示:

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))

关于c# - Linq 在没有 .GroupBy() 的情况下获取不同的有序元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44217726/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com