web-dev-qa-db-fra.com

LINQ to SQL: GroupBy () et Max () pour obtenir l'objet avec la dernière date

Considérez une table SQL Server utilisée pour stocker des événements pour l'audit.

Le besoin est d'obtenir uniquement la dernière entrée pour chaque CustID. Nous voulons obtenir l'objet/la ligne entière. Je suppose qu'un GroupBy () sera nécessaire dans la requête. Voici la requête jusqu'à présent:

var custsLastAccess = db.CustAccesses   
                        .Where(c.AccessReason.Length>0)
                        .GroupBy(c => c.CustID)
//                      .Select()
                        .ToList();
// (?) where to put the c.Max(cu=>cu.AccessDate) 

Custs Layout

Question: Comment puis-je créer la requête pour sélectionner le dernier (maximum AccessDate) enregistrement/objet pour chaque CustID?

37
p.campbell

Je me demande si quelque chose comme:

var custsLastAccess = db.CustAccesses   
                    .Where(c.AccessReason.Length>0)
                    .GroupBy(c => c.CustID)
                    .Select(grp => new {
                      grp.Key,
                      LastAccess = grp
                         .OrderByDescending(x => x.AccessDate)
                         .Select(x => x.AccessDate)
                         .FirstOrDefault()
                    }).ToList();

vous pouvez également essayer OrderBy() et Last()

36
Marc Gravell

Utilisation de la syntaxe LINQ, qui me semble plus propre:

var custsLastAccess = from c in db.CustAccesses 
                      group c by c.CustID into grp
                      select grp.OrderByDescending(c => c.AccessDate).FirstOrDefault();
27
CodeGrue

Ici: cela utilise max plutôt que OrderByDesc, donc devrait être plus efficace.

var subquery = from c in CustAccesses
            group c by c.CustID into g
            select new
            {
                CustID = g.Key,
                AccessDate = g.Max(a => a.AccessDate)
            };
var query = from c in CustAccesses
            join s in subquery 
              on c.CustID equals s.CustID
            where c.AccessDate == s.AccessDate
             && !string.IsNullOrEmpty(c.AccessReason)
            select c;
5
Gary
var custsLastAccess = db.CustAccesses   
                            .Where(c.AccessReason.Length>0)
                        .GroupBy(c => c.CustID, (id, custs) => new { ID=id, LastAccess=custs.OrderByDescending(c=>c.AccessDate).First().AccessDate})
                      .Select()
                        .ToList();
0
vladhorby