简体   繁体   中英

Linq Group By Object Then Select

I'm looking to group records by their LeagueId and Date . Then order desc on the date and then select the first occurrence of a distinct LeagueId . So far I have something like this but I don't know how to select stats in the first occurrence of a distinct LeagueId .

var stats =
    _statsRepository.FindBy(x => x.Active)
         .GroupBy(x => new { x.LeagueId, x.Date })
         .OrderByDescending(x => x.Key.Date)
         .SelectMany(x => x);

Its pretty much a way to get the most recent stats per league. So League 1 = 12/02/2017 and league 2 could be 02/02/17. <--- disregard this, may be misleading.

There are many stat records that occur on a date in a league. So for a certain date with each league there would be multiple stats.

Record 1:
09/01/14,
Jim,
4 Goals,
League 1

Record 2:
13/01/14,
Jack,
2 Goals,
League 1

Record 3:
13/01/14,
James,
2 Goals,
League 1

Record 4:
15/01/14,
Hannah,
2 Goals,
League 2

Record 5:
15/01/14,
Harmony,
1 Goal,
League 2

Record 6:
10/01/14,
Alision,
3 Goals,
League 2

The records that should be selected are

Record 2:
13/01/14,
Jack,
2 Goals,
League 1

Record 3:
13/01/14,
James,
2 Goals,
League 1

Record 4:
15/01/14,
Hannah,
2 Goals,
League 2

Record 5:
15/01/14,
Harmony,
1 Goal,
League 2

Explanation : For league 1 Records 2 & 3 occurs later than record 1 so they are both selected. For league 2 records 4 & 5 should be selected as they are the latest date.

With the latest update, you need to group by LeagueId and simply get all the records from each grouping with Date equals max Date in the grouping:

var stats = _statsRepository.FindBy(x => x.Active)
    .GroupBy(x => x.LeagueId)  
    .SelectMany(g => g.Where(x => x.Date == g.Max(y => y.Date));

Another way to get the same result is to use !Any (SQL NOT EXISTS ) construct:

var baseStats = _statsRepository.FindBy(x => x.Active);
var stats = baseStats
    .Where(x => !baseStats.Any(y => y.LeagueId == x.LeagueId && y.Date > x.Date));

I assume you work with IQueryable s (ie not LINQ to Objects where such things matter), so no optimizations like intermediate Select s are needed.

You want to group by league then take the most recent date in the group for each league

var stats = _statsRepository.FindBy(x => x.Active)
            .GroupBy(x => new { x.LeagueId, x.Date })
            .GroupBy(g => g.Key.LeagueId)
            .Select(gg => new { LeagueId = gg.Key, Stats = gg.OrderByDescending(g => g.Key.Date).First().ToList() })
            .ToList();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM