webentwicklung-frage-antwort-db.com.de

Wie bekomme ich in LINQ eine Zeile für jeden Schlüssel?

Ich habe eine Liste mit:

 EMP_ID | UPDATED_DATE | MARK 
------ | ------------ | ----
 111 | 01/01/2015 | 99 
 111 | 01.01.2013 | 85 
 111 | 01.01.2017 | 80 ... 222 | 01/01/2011 | 70 
 222 | 01/01/2015 | 55 
 222 | 01/01/2002 | 60 

Ich muss für jede ID eine Zeile mit dem neuesten UPDATED_DATE, Auswählen. In unserem etc:

 EMP_ID | UPDATED_DATE | MARK 
------ | ------------ | ----
 111 | 01.01.2017 | 80 ... 222 | 01/01/2015 | 55 

Dies ist der Code für die Bestellung:

empMarksList.OrderBy(x=>x.EMP_ID).ThenBy(y=>y.UPDATED_DATE)
9
user1012506

Verwenden Sie GroupBy:

var items = empMarksList
                   .GroupBy(e => e.EMP_ID)
                   .Select(grp => grp.OrderByDescending(v => v.UPDATED_DATE).First());

Oder wenn Sie ein Wörterbuch wünschen:

var dict = empMarksList
              .GroupBy(e => e.EMP_ID)
              .ToDictionary(grp => grp.Key,
                            grp => grp.OrderByDescending(v => v.UPDATED_DATE).First());
11
Amir Popovich

Eine weitere Option ist:

var items = context.EmpMarks
    .GroupBy(e => e.EMP_ID, (k, g) => g
        .FirstOrDefault(e => g.Max(v => v.UPDATED_DATE) == e.UPDATED_DATE));

Was sollte eigentlich GROUP BY in SQL generieren.

3
arekzyla

Ich bevorzuge diese Variante, aber es ist dasselbe wie Amirs Antwort

var query =
    empMarksList
        .GroupBy(x => x.EMP_ID)
        .SelectMany(x => x.OrderByDescending(y => y.UPDATED_DATE).Take(1));
3
Enigmativity

Sie können so etwas verwenden: 

var result = empMarksList.GroupBy(x => x.Id)
    .Select(g => 
        g.Aggregate((a, x) => a == null || a.UPDATRED_DATE < x.UPDATRED_DATE ? x : a));

Es ist etwas umständlicher als die Verwendung von OrderBy, aber auf diese Weise werden Sie nicht alle Untersammlungen bestellen, was hier ein wenig übertrieben ist und mehr Ressourcen erfordert.

EDIT: Nach einer Antwort von @arekzyla wurde mir klar, dass meine Option auch so geschrieben werden kann:

var items = empMarksList.GroupBy(
   x => x.Id,
   (k, g) => g.Aggregate((a, x) => a == null || a.UPDATRED_DATE < x.UPDATRED_DATE ? x : a));

Es ist weniger lesbar, hat jedoch statt zwei Sammlungen eine Durchsuchung der Sammlungen, was in den meisten Fällen vernachlässigbar ist.

Ich bin mir nicht sicher, in welchem ​​Fall die von SQL generierte Version optimaler wäre. Es lohnt sich also zu prüfen.

1
Andrey Tretyak