Comment sélectionner uniquement les enregistrements avec la date la plus élevée dans LINQ

117

J'ai une table, «lasttraces», avec les champs suivants.

Id, AccountId, Version, DownloadNo, Date

Les données ressemblent à ceci:

28092|15240000|1.0.7.1782|2009040004731|2009-01-20 13:10:22.000
28094|61615000|1.0.7.1782|2009040007696|2009-01-20 13:11:38.000
28095|95317000|1.0.7.1782|2009040007695|2009-01-20 13:10:18.000
28101|15240000|1.0.7.1782|2009040004740|2009-01-20 14:10:22.000
28103|61615000|1.0.7.1782|2009040007690|2009-01-20 14:11:38.000
28104|95317000|1.0.7.1782|2009040007710|2009-01-20 14:10:18.000

Comment puis-je, dans LINQ to SQL , obtenir uniquement la dernière trace de chaque AccountId (celui avec la date la plus élevée)?

Bas Jansen
la source
En fait, dans votre exemple, tous les journaux avec le même identifiant de compte ont exactement la même date, alors lequel a la préférence dans ce cas?
BlackTigerX

Réponses:

231

Si vous voulez juste la dernière date pour chaque compte, vous utiliserez ceci:

var q = from n in table
        group n by n.AccountId into g
        select new {AccountId = g.Key, Date = g.Max(t=>t.Date)};

Si vous voulez l'intégralité de l'enregistrement:

var q = from n in table
        group n by n.AccountId into g
        select g.OrderByDescending(t=>t.Date).FirstOrDefault();
Mehrdad Afshari
la source
2
Oracle ne prend pas en charge cela. Si les performances des requêtes ne sont pas prises en compte, vous pouvez convertir la table ToList avant d'effectuer la requête.
Will Wu
8
Ce serait formidable si vous pouviez publier une method-chainsolution pour cela.
LCJ
deuxième question - ne devrait-il pas être (from n in table ...).First()?
Jason L
@JasonL, non. L' First()appel doit s'appliquer à l' g.Order...expression (sous-requête).
Mehrdad Afshari
1
@Mehrdad Afshari c'est incroyable , je voulais principalement le second, mais ils sont tous les deux maintenant dans mes extraits comme très utiles . Merci merci merci!!!!!
Andrew Day
52

Voici un moyen simple de le faire

var lastPlayerControlCommand = this.ObjectContext.PlayerControlCommands
                                .Where(c => c.PlayerID == player.ID)
                                .OrderByDescending(t=>t.CreationTime)
                                .FirstOrDefault();

Jetez également un œil à cet excellent endroit LINQ - Exemples LINQ to SQL

Développeur
la source
25
Cette solution fonctionne très bien si vous interrogiez par compte mais ne fait pas ce que OP a déclaré, qui est d'obtenir le résultat le plus récent pour tous les enregistrements sans fournir un AccountId (dans votre cas PlayerId)
Maciej
1
Cette solution m'a inspiré à commander plutôt pour essayer de sélectionner le maximum. +1
Razvan Dumitru
Cette solution peut conduire à une erreur "La séquence ne contient aucun élément" dans Linq, non?
xSkrappy
34

Si vous voulez tout l'enregistrement, voici une méthode lambda:

var q = _context
             .lasttraces
             .GroupBy(s => s.AccountId)
             .Select(s => s.OrderByDescending(x => x.Date).FirstOrDefault());
Bob Zhang
la source
1
A très bien fonctionné. Merci.
Terry
C'est la clé ici.
Jason P Sallinger
5

Cela pourrait être quelque chose comme:

var qry = from t in db.Lasttraces
          group t by t.AccountId into g
          orderby t.Date
          select new { g.AccountId, Date = g.Max(e => e.Date) };
bruno conde
la source
3

Allez d'une manière simple de faire ceci: -

Création d'une classe pour contenir les informations suivantes

  • Niveau (nombre)
  • Url (URL du site)

Accédez à la liste des sites stockés sur un objet ArrayList. Et exécuté la requête suivante pour la trier par ordre décroissant par niveau.

var query = from MyClass object in objCollection 
    orderby object.Level descending 
    select object

Une fois que j'ai trié la collection par ordre décroissant, j'ai écrit le code suivant pour obtenir l'objet qui vient en haut

MyClass topObject = query.FirstRow<MyClass>()

Cela a fonctionné comme un charme.

Sudhir Kesharwani
la source
Cela m'a donné une meilleure idée que ma pensée originale. Merci!
Paulj