6

I have a database with 4 fields that looks something like this:

ID      DeviceId       Location        Date
1           A             ...            2
2           A             ...            1
3           B             ...            2

For each DeviceId I want the location from the record with the highest date. I can get the distinct DeviceId's like this:

// get all locations
var locations = Session.Query<Location>().ToList();

//Get the latest used unique deviceId's
var distinctDeviceIdsByDate = (
      from loc in locations
      orderby loc.DeviceId, loc.Date descending
      select loc.DeviceId).Distinct().ToList();

I would then use join to get the wanted rows, but this won't do any good since I can't get anything other than the DeviceId's and therefore can't identify which rows to select. and if I try to select the following:

select loc

I can only get the rows with unique combinations of all the columns. I'm sure there's a simple solution, but I'm afraid I can't figure it out right now.

3
  • 2
    So for each device ID you want the location from the record with the highest date? Commented Mar 12, 2013 at 14:49
  • Yes, exactly! I'll edit the question to say what you said. Commented Mar 12, 2013 at 14:52
  • You shouldn't edit the question to include the answer; you should mark the one you think is correct or help you the most. Commented Mar 12, 2013 at 15:33

3 Answers 3

7

I guess you have to use some combination of GroupBy and Take. Try this,

var distinctDeviceIdsByDate = 
    locations.OrderByDescending(location => location.DeviceId)
             .ThenByDescending(location => location.Date)
             .GroupBy(location => location.DeviceId)
             .SelectMany(location => location.Take(1));
Sign up to request clarification or add additional context in comments.

1 Comment

Looks like this works the way I want! I will update the question with your solution, accredited to you!
1

Assuming that Date is unique per DeviceId you could try

//Get the latest used unique deviceId's
var distinctDeviceIdsByDate = (
      from loc in Session.Query<Location>()
      group loc by loc.DeviceId
      into g
      select new
      {
          DeviceID = g.Key,  
          Location = g.OrderByDescending(l => l.Date).First().Location;
      };

2 Comments

This looks like a possible solution aswell, but since the answer from DotNetWala worked I will use it for now and investigate other solutions should I encounter problems down the road.
This will not work with NHibernate and will throw the following SqlException: Column 'Location.Date' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
0

You can use a grouping to solve this.

var locations = new [] {
    new { DeviceId = "A", Date = 2, Location = ".." },
    new { DeviceId = "A", Date = 1, Location = ".." },
    new { DeviceId = "B", Date = 2, Location = "...." },
};

var lastUsedLocations = 
    from l in locations
    group l by l.DeviceId into g
    let lastUsed = g.OrderBy(x => x.Date).Last()
    select lastUsed;

// lastUsedLocations contains
// DeviceId       Date        Location
// A              2           ..
// B              2           ....

2 Comments

This looks like a possible solution aswell, but since the answer from DotNetWala worked I will use it for now and investigate other solutions should I encounter problems down the road.
They are essentially the same. The key concept is grouping.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.