Come selezionare solo i record con la data più alta in LINQ


117

Ho una tabella, "lasttraces", con i seguenti campi.

Id, AccountId, Version, DownloadNo, Date

I dati hanno questo aspetto:

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

Come posso, in LINQ to SQL , ottenere solo l'ultima ultima traccia di ogni AccountId (quello con la data più alta)?


in realtà nel tuo esempio tutti i log con lo stesso ID account hanno la stessa identica data, quindi quale ha la preferenza in quel caso?
BlackTigerX

Risposte:


230

Se vuoi solo l'ultima data per ogni account, dovresti usare questo:

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

Se vuoi l'intero record:

var q = from n in table
        group n by n.AccountId into g
        select g.OrderByDescending(t=>t.Date).FirstOrDefault();

2
Oracle non lo supporta. Se le prestazioni delle query sono fuori dalla tua considerazione, puoi convertire la tabella ToList prima di eseguire la query.
Will Wu l'

8
Sarebbe fantastico se potessi pubblicare una method-chainsoluzione per questo.
LCJ

seconda domanda - non dovrebbe essere (from n in table ...).First()?
Jason L

@ JasonL, no. La First()chiamata dovrebbe essere applicata g.Order...all'espressione (sottoquery).
Mehrdad Afshari

1
@Mehrdad Afshari è fantastico , volevo principalmente il secondo, ma ora sono entrambi nei miei frammenti in quanto molto utili . Grazie, grazie, grazie!!!!!
Andrew Day

52

Ecco un modo semplice per farlo

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

Dai un'occhiata anche a questo fantastico posto LINQ : LINQ to SQL Samples


25
Questa soluzione funziona bene se stavi interrogando per account ma non fa quanto dichiarato da OP, ovvero ottenere il risultato più recente per tutti i record senza fornire un AccountId (nel tuo caso PlayerId)
Maciej

1
Questa soluzione mi ha spinto a ordinare invece di provare a selezionare il massimo. +1
Razvan Dumitru

Questa soluzione può portare all'errore "La sequenza non contiene elementi" in Linq, giusto?
xSkrappy

34

Se vuoi l'intero record, ecco un modo lambda:

var q = _context
             .lasttraces
             .GroupBy(s => s.AccountId)
             .Select(s => s.OrderByDescending(x => x.Date).FirstOrDefault());

1
Ha funzionato alla grande. Grazie.
Terry

Questa è la chiave qui.
Jason P Sallinger,

5

Potrebbe essere qualcosa del tipo:

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

3

Procedi in un modo semplice per farlo: -

Creata una classe per contenere le seguenti informazioni

  • Livello (numero)
  • Url (Url del sito)

Vai all'elenco dei siti archiviati in un oggetto ArrayList. Ed eseguito la seguente query per ordinarlo in ordine decrescente per Livello.

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

Una volta che ho ottenuto la raccolta ordinata in ordine decrescente, ho scritto il codice seguente per ottenere l'oggetto che si trova nella riga superiore

MyClass topObject = query.FirstRow<MyClass>()

Questo ha funzionato a meraviglia.


Questo mi ha dato un'idea migliore del mio pensiero originale. Grazie!
Paulj
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.