簡體   English   中英

取LINQ中每個分組項目的Top(X)

[英]Take Top(X) of each grouped item in LINQ

我正在嘗試為列中的每個唯一項都選擇Top(X)記錄器。

例:

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-Objects中運行良好。 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有關,盡管羅伯特發表的最后一個查詢在技術上是正確的,可以解決。

由於IQueryable的性質,直到必要時才枚舉,這將生成一個SQL腳本。 SQL本身會生成“ Where Exists”子句。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM