132

I have a table, 'lasttraces', with the following fields.

Id, AccountId, Version, DownloadNo, Date

The data looks like this:

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

How can I, in LINQ to SQL, only get the last lasttrace of every AccountId (the one with the highest date)?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Bas Jansen
  • 1,710
  • 2
  • 14
  • 12
  • actually in your example all logs with the same account id, have the exact same date, so which one takes preference in that case? – BlackTigerX Jan 22 '09 at 20:05

6 Answers6

251

If you just want the last date for each account, you'd use this:

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

If you want the whole record:

var q = from n in table
        group n by n.AccountId into g
        select g.OrderByDescending(t=>t.Date).FirstOrDefault();
Ravi Ram
  • 24,078
  • 21
  • 82
  • 113
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
57

Here is a simple way to do it

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

Also have a look this great LINQ place - LINQ to SQL Samples

NoWar
  • 36,338
  • 80
  • 323
  • 498
  • 31
    This solution works fine if you were querying per account but does not do what OP stated, which is to get the most recent result for all records without providing an AccountId (in your case PlayerId) – Maciej May 03 '13 at 18:30
  • 1
    This solution inspired me to order instead to try to select the maximum. +1 – Razvan Dumitru Apr 15 '14 at 12:07
  • This solution may lead to "Sequence contains no elements" Error in Linq right? – xSkrappy Nov 15 '18 at 06:06
50

If you want the whole record,here is a lambda way:

var q = _context
             .lasttraces
             .GroupBy(s => s.AccountId)
             .Select(s => s.OrderByDescending(x => x.Date).FirstOrDefault());
Quantum
  • 1,456
  • 3
  • 26
  • 54
Bob Zhang
  • 841
  • 3
  • 10
  • 17
6

It could be something like:

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
  • 47,767
  • 15
  • 98
  • 117
3

Go a simple way to do this :-

Created one class to hold following information

  • Level (number)
  • Url (Url of the site)

Go the list of sites stored on a ArrayList object. And executed following query to sort it in descending order by Level.

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

Once I got the collection sorted in descending order, I wrote following code to get the Object that comes as top row

MyClass topObject = query.FirstRow<MyClass>()

This worked like charm.

0

LINQ's .OrderByDescending().FirstOrDefault() approach is good. But the https://github.com/morelinq/MoreLINQ people do it better: .MaxBy()

Example:

IEnumerable<Person> data = Data.GetPersons();
Person oldestPerson = data.MaxBy(p => p.Age);

Or in the latest version of MoreLINQ, they have changed the return type:

IEnumerable<Person> data = Data.GetPersons();
IEnumerable<Person> oldestPersons = data.MaxBy(p => p.Age);
Person oldestPerson = oldestPersons.First();

So what used to be .MaxBy() is now .MaxBy().First(). This has the advantage that you can handle more than 1 result (used to be only the first person with the max age, but there may be more persons with the same age). Another advantage is that .MaxBy() can now handle an empty IEnumerable<T> without throwing an exception. Of course, the exception occurs in .First() then, but you can decide to use .FirstOrDefault() instead to avoid this.

Kim Homann
  • 3,042
  • 1
  • 17
  • 20