tags:

views:

434

answers:

6

I have a table that looks like this. The query needs to return the last date entry for each location. How would I write this in SQL and LINQ?

Id  Location        Salary  Date
1   Los Angeles     $1500   Jan-05-1999 
2   San Diego       $250    Jan-07-1999 
3   Los Angeles     $300    Jan-08-1999
4   Boston          $700    Jan-08-1999
5   Los Angeles     $300    Jan-08-1999

The result would be:

2   San Diego       $250    Jan-07-1999
4   Boston          $700    Jan-08-1999
5   Los Angeles     $300    Jan-08-1999
A: 
SELECT location, max(date)

FROM yourtable

GROUP BY location

EDIT: I didn't see the results being asked for or not sure if it was there originally:

SELECT yourtable.id, yourtable.location, yourtable.salary, yourtable.date
FROM yourtable INNER JOIN
  (SELECT yourtable.location, MAX(yourtable.date) as thedate
   FROM yourtable
   GROUP BY yourtable.location) AS MYRESULT 
   on MYRESULT.thedate = yourtable.date  
      AND MYRESULT.location = yourtable.location

Haven't tested this though.

BobbyShaftoe
+1  A: 

Keep in mind I'm pretty new to link, and I don't think this is the best way:

var collection = from d in <TABLE> select d;
collection = collection.GroupBy(x => x.Date).Select(x => x.Last());

Basically just group on the date and take the last one. I couldn't think of a good way to do this in the LINQ command, so I just selected all the rows - anyone know to combine these lines?

Steve Willard
Yes, you can simply replace collection with TABLE in line 2.
leppie
A: 

@Bobby Shaftoe

I believe that he was looking for the latest entry rather than the latest date for every location. If my assumption is correct, it would be more like

SELECT max(ID),location,date
FROM tablename
GROUP BY location
bioskope
Well, he said date entry. However, if his data is consistent, it looks like it would be the same thing, perhaps. But I stick with what I have based on the question was written, you might be right though.
BobbyShaftoe
Oh, and there is a mistake in this one. The DB will complain that "date" is not in group by clause or in an aggregate function.
BobbyShaftoe
He has the result he expects here - it's the full row. Not sure if it was there originally though.
Damovisa
yes the result is a full row
A: 

To get the whole row with the max date for each location, I think the SQL is:

SELECT t1.Id, t1.Location, t1.Salary, t1.Date
FROM YourTable t1, 
    (SELECT Location, MAX(Date) AS MaxDate
    FROM YourTable
    GROUP BY Location) t2
WHERE t1.Location = t2.Location
AND t1.Date = t2.MaxDate

Please correct me if I'm wrong!

Damovisa
how would you write this in LINQ?
Yeah, great question :) The short answer is I don't know Linq well enough.I know linq tends to mirror sql somewhat, but I don't know the exact syntax (if there is one) for grouping and joining.You may have to follow Steve Willard's example - select everything and pare it down using expressions.
Damovisa
A: 

Actually, this is not so straight forward if I read this question correctly. Because Los Angeles has 2 entries on the Max date there appears to be a further rule that in that situation the max ID should be selected.

In that case the SQL becomes a little more complex, 2 groupings are required....

select id, location, salary, date from 
locations where id in
(select  max(id) as MaxID
from locations where date in (
Select Max(Date) as MaxDate from Locations group by Location)
Group by location)

The corresponding Linq query, would also require 2 groupings...

  var qry = from a in locations
            group a by a.Location into grp
            from b in grp
            where b.Date == grp.Max(o => o.Date)
            group b by b.Location into grp2
            from c in grp2
            where c.ID == grp2.Max(obj => obj.ID)
            orderby c.ID
            select c;
Tim Jarvis
+1  A: 

If your dates included time, then you could:

var locations = 
   from l in mycontext.Locations
   where l.Date = mycontext.Locations
         .Where(l2=>l.Location == l2.Location)
         .Max(l2.Date)
   select l;

Alternatively, assuming ID is an identity and the records are inserted in the table when they occurred(your example seems to hint so), you can do:

var locations = 
   from l in mycontext.Locations
   where l.ID = mycontext.Locations
         .Where(l2=>l.Location == l2.Location)
         .Max(l2.ID)
   select l;
eglasius