取 LINQ 中每个分组项的 Top(X)
本文关键字:Top LINQ | 更新日期: 2023-09-27 18:18:31
我正在尝试为列中的每个唯一项目获取 Top(X( recors。
例:
Inspections
InspectionId | RestaurauntName | InspectionDate
------------------------------------------------
1 Mom&Pop 10/10/12
2 SandwichesPlace 10/10/12
3 Mom&Pop 10/10/11
4 SandwichesPlace 10/10/11
5 Mom&Pop 10/10/10
6 SandwichesPlace 10/10/10
7 BurgerPlace 10/10/11
8 BurgerPlace 10/10/09
9 BurgerPlace 10/10/08
如果我传递"2"的值作为参数,我希望返回记录 1、2、3、4、7、8。
在此示例片段中,我尝试为每个"restaurantName"获取一些记录。
public IQueryable<Inspections>
GetLatestInspectionDatesForAllRestaurants(int numRecords) {
IQueryable<Inspections> inspections= _session.Query<Inspections>()
.GroupBy(r=> r.RestaurauntName)
.SelectMany(g => g
.OrderBy(r => r.InspectionDate)
.Take(numRecords));
return inspections;
}
不幸的是,我收到此错误。
Query Source could not be identified:
ItemName = g, ItemType = System.Linq.IGrouping`2
此时在代码中触发异常
var inspections = _inspectionRepository.GetLatestInspectionDatesForAllRestaurants(2).ToList();
我错过了什么?
编辑
运行测试后,我已确认查询在 LINQ To 对象中运行良好。NHibernate.Linq在这方面是否仍然不完整?我做了一个稍微不同的查询(下面(,并得到了一个未实现的异常。
.GroupBy(r=> r.RestaurauntName)
.Select(g => g.First()).Take(5)
如果我从末尾删除 Take(5(,我会得到以下内容(提醒这是一个示例,在我的真实情况下,我的 PK 是 Id(。
{"Column '.Id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause."}
我需要学习使用创建条件或其他东西吗?
好吧,我得到了我需要的SQL生成,这需要一些研究等等。我确信我最初的问题与 LINQ 和 NHibernate 有关,尽管 Robert 发布的最后一个查询作为解决方法在技术上是正确的。
这将生成单个 SQL 脚本,因为 IQueryable 的性质是在必要时不枚举。SQL 本身生成"存在何处"子句。
public IQueryable<Inspections>
GetLatestInspectionDatesForAllRestaurants(int numRecords)
{
var subQuery = _session.Query<Inspections>()
.OrderByDescending(x => x.InspectionDate);
var inspections = _session.Query<Inspections>()
.Where(x => subQuery.Where(y => y.InspectionDate ==
x.InspectionDate).Take(numRecords).Contains(x))
.OrderBy(x => x.WellDataId);
return inspections;
}
就是这样,希望它最终能帮助其他人。
public class Inspections{
public int InspectionId {get;set;}
public string RestaurantName {get;set;}
public DateTime InspectionDate {get;set;}
}
void Main()
{
var result=GetLatestInspectionDatesForAllRestaurants(2);
result.Dump();
}
public IQueryable<Inspections>
GetLatestInspectionDatesForAllRestaurants(int numRecords) {
var i = new[]{
new Inspections{InspectionId=1,RestaurantName="Mom&Pop",InspectionDate=DateTime.Parse("10/10/12")},
new Inspections{InspectionId=2,RestaurantName="SandwichesPlace",InspectionDate=DateTime.Parse("10/10/12")},
new Inspections{InspectionId=3,RestaurantName="Mom&Pop",InspectionDate=DateTime.Parse("10/10/11")},
new Inspections{InspectionId=4,RestaurantName="SandwichesPlace",InspectionDate=DateTime.Parse("10/10/11")},
new Inspections{InspectionId=5,RestaurantName="Mom&Pop",InspectionDate=DateTime.Parse("10/10/10")},
new Inspections{InspectionId=6,RestaurantName="SandwichesPlace",InspectionDate=DateTime.Parse("10/10/10")},
new Inspections{InspectionId=7,RestaurantName="BurgerPlace",InspectionDate=DateTime.Parse("10/10/11")},
new Inspections{InspectionId=8,RestaurantName="BurgerPlace",InspectionDate=DateTime.Parse("10/10/09")},
new Inspections{InspectionId=9,RestaurantName="BurgerPlace",InspectionDate=DateTime.Parse("10/10/08")}
};
var result=i.GroupBy(g=>g.RestaurantName).SelectMany(g=>g.OrderByDescending(d=>d.InspectionDate).Take(2));
return result.AsQueryable();
}
这运行良好,所以我假设您的原始可查询对象的生存期有问题。 请尝试以下操作:
public IQueryable<Inspections>
GetLatestInspectionDatesForAllRestaurants(int numRecords)
{
IQueryable<Inspections> inspections= _session.Query<Inspections>()
.GroupBy(r=> r.RestaurauntName)
.SelectMany(g => g
.OrderByDescending(r => r.InspectionDate)
.Take(numRecords));
return inspections.ToList().AsQueryable();
}
这是第三个选项,性能不佳,但应该从等式中消除 NHibernate:
public IQueryable<Inspections>
GetLatestInspectionDatesForAllRestaurants(int numRecords)
{
IQueryable<Inspections> inspections= _session.Query<Inspections>().ToList()
.GroupBy(r=> r.RestaurauntName)
.SelectMany(g => g
.OrderByDescending(r => r.InspectionDate)
.Take(numRecords));
return inspections.ToList().AsQueryable();
}