2009-12-18 7 views
6

Ho un gruppo di righe raggruppate su un attributo chiamato MyID. Ora voglio l'unica riga di ogni gruppo in cui l'attributo StatusDate è il più alto in quel gruppo.LINQ: Ottenere la riga con il valore massimo di un determinato attributo

Questo è quello che mi è venuto in mente.

rows.Select(x => x.Where(y => y.StatusDate == x.Max(z => z.StatusDate)).First()) 

Con un po 'più spiegazione:

rows.Select(x => // x is a group 
    x.Where(y => // get all rows in that group where... 
       // the status date is equal to the largest 
       // status date in the group 
    y.StatusDate == x.Max(z => z.StatusDate) 
).First()) // and then get the first one of those rows 

Esiste un modo più veloce o più idiomatico per fare questo?

+0

Perché selezioni tutte le righe con il più grande DateTime, ma scegli solo il primo? Se non ti interessa quale riga "massimizzata" scegli, forse dovresti sostituire la x.Where (...). Prima() con x.Max (...). –

+0

@Vlad: aggiungilo come risposta e lo accetterò. Ha perfettamente senso. –

+1

'x.Max (...)' non restituirà l'intera riga, ma solo il valore massimo. –

risposta

15

Un'alternativa sarebbe quella di utilizzare:

rows.Select(x => x.OrderByDescending(y => y.StatusDate).First()); 

... e verificare che l'ottimizzatore di query sa che non davvero necessità di risolvere tutto. (Questo sarebbe disastroso in LINQ to Objects, ma si potrebbe usare MaxBy da MoreLINQ in quel caso :)

(Ci scusiamo per la versione precedente -. Non avevo pienamente compreso il bit di raggruppamento)

+0

Un po 'fuori tema ma ... Puoi pubblicare un esempio o collegare un luogo in cui possiamo vedere MoreLINQ in azione? Quel 'MaxBy' mi ha davvero entusiasmato. –

+0

@Alex: intendi solo codice di esempio? In questo caso sarebbe 'rows.Select (x => x.MaxBy (y => y.StartDate))' - ma non abbiamo una "vetrina" di queste cose, che forse dovremmo ... –

+0

Questa è una buona opzione, ma è difficile per me dire quali risultati in un più efficiente TSQL di runtime. La tua soluzione è già abbastanza buona. Avrei eseguito entrambe queste operazioni tramite il debugger per scoprire che aspetto avesse il TSQL generato, quindi eseguirlo direttamente tramite SQL Management Studio e dare un'occhiata ai piani di esecuzione, e magari eseguirlo anche attraverso l'analisi delle prestazioni e/o il profiler . –

0

Non sapere se si tratta di Linq to SQL, ma se lo è, si potrebbe in alternativa eseguire tramite una funzione rank() in SQL (classificare ciascun gruppo per data, quindi selezionare la prima riga classificata da ciascuno), quindi chiamare questo come un processo memorizzato da LINQ. Penso che sia un approccio che sta diventando più idiomatico quando le persone colpiscono i confini di LINQ2SQL ...

Problemi correlati