2009-12-18 12 views
6

Mam kilka wierszy zgrupowanych w atrybucie o nazwie MyID. Teraz chcę jeden wiersz z każdej grupy, w której atrybut StatusDate jest najwyższy w tej jednej grupie.LINQ: Uzyskiwanie wiersza z maksymalną wartością określonego atrybutu

Oto, co wymyśliłem.

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

Z nieco więcej wyjaśnień:

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 

Czy istnieje szybciej lub bardziej idiomatycznych sposób to zrobić?

+0

Dlaczego wybierasz wszystkie wiersze z największą datą czasową, ale wybierasz tylko pierwsze? Jeśli nie zależy ci na wyborze "zmaksymalizowanego" rzędu, być może powinieneś zastąpić x.Where (...). First() z x.Max (...). –

+0

@ Vlad: Dodaj to jako odpowiedź, a ja to zaakceptuję. Ma doskonały sens. –

+1

'x.Max (...)' nie zwróci całego wiersza - tylko wartość maksymalna. –

Odpowiedz

15

Alternatywą byłoby użyć:

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

... i sprawdzić, że optymalizator kwerendy wie, że nie naprawdę trzeba posortować wszystko. (To byłoby katastrofalne w LINQ to Objects, ale można użyć MaxBy z MoreLINQ w tym przypadku :)

(przeprosiny za poprzedniej wersji. - I nie w pełni zrozumiana bitu grupowania)

+0

Trochę nie na temat, ale ... Czy możesz podać przykład lub powiązać miejsce, w którym możemy zobaczyć MoreLINQ w akcji? Ten "MaxBy" naprawdę mnie zachwycił. –

+0

@Alex: Masz na myśli tylko przykładowy kod? W tym przypadku będzie to 'rows.Select (x => x.MaxBy (y => y.StartDate))' - ale nie mamy "wizytówki" tych rzeczy, które być może powinniśmy ... –

+0

Jest to dobra opcja, ale trudno mi powiedzieć, co powoduje bardziej wydajne środowisko wykonawcze TSQL. Twoje własne rozwiązanie jest już całkiem niezłe. Uruchomiłbym oba te elementy za pomocą debuggera, aby dowiedzieć się, jak wygląda wygenerowany TSQL, a następnie uruchomić wszystkie bezpośrednio za pomocą SQL Management Studio i przyjrzeć się planom wykonania, a może nawet uruchomić je za pomocą analizatora wydajności i/lub profilera. . –

0

Nie wiem, czy to jest Linq do SQL, ale jeśli tak, możesz alternatywnie wykonać poprzez funkcję rang() w SQL (uszereguj każdą grupę według daty, następnie wybierz pierwszy wiersz z każdego), a następnie nazwij to jako zapisany proc z LINQ. Myślę, że jest to aplikacja, która staje się coraz bardziej idiotyczna, gdy ludzie trafiają na granice LINQ2SQL ...

Powiązane problemy