Is it possible to do a GROUP BY in SQL Server 2000 that returns the whole row?
I have an SQL Server 2000 database that contains a view that shows meter readings for supply points which has the following columns:
- rh_sp_number <- the number of the supply point
- rh_... <- a bunch of other columns pertaining to that specific reading row
- rh_end_date <- a `DateTime`field that holds the date of the reading
Each SupplyPoint can have 0..N readings. I need to fetch the last submitted row for any given SupplyPoint. And I want to accomplish this with one query to the Database.
I need to do something like this:
var q = db.READINGS_HISTORY.Where(rh => ids.Contains(rh.rh_sp_number))
.GroupBy(rh => rh.rh_sp_number, rh => rh,
(key, values) => values.OrderByDescending(rh => rh.rh_end_date).FirstOrDefault())
.ToList();
In human language I need to select the last row of each group and return that row. Running this query (or any other combination that I could think of) will result in this:
The execution of this query requires the APPLY operator, which is not supported in versions of SQL Server earlier than SQL Server 2005.
I need to accomplish this in SQL Server 2000.
It does not have to be a 'Group By' expression; anything that will return a maximum row for a given key will do.
My solution:
Based on Aarons answer I ended up with this query that does what I need (with a caveat, but business rules remove it form the equation for me).
The caveat: if there are same dates for same SupplyPoints the sql server will decide which row to choose
var hists = db.READINGS_HISTORY.Where(rh => ids.Contains(rh.rh_sp_number))
.GroupBy(rh => rh.rh_sp_number, rh => rh,
(key, values) =>开发者_运维百科 new { key, date = values.Max(rh => rh.rh_end_date) })
.Join(db.READINGS_HISTORY, g => new { sp = g.key, date = g.date },
rh2 => new { sp = rh2.rh_sp_number, date = rh2.rh_end_date }, (g, rh) => rh)
.Select(rh => new LastReading
{
//omitted..
}).ToList();
I have absolutely no clue how to write this in linq-to-entities, but here is the general methodology in straight T-SQL (assuming that rh_sp_number is the column you want to group by).
SELECT rh.rh_sp_number, rh.rh_end_date /*, ... other cols ... */
FROM dbo.Readings_History AS rh
INNER JOIN
(
SELECT rh_sp_number, rh_end_date = MAX(rh_end_date)
FROM dbo.Readings_History
GROUP BY rh_sp_number
) AS sub
ON rh.rh_sp_number = sub.rh_sp_number
AND rh.rh_end_date = sub.rh_end_date;
Note that you don't specify what to do with ties (two rows with the same rh_sp_number and rh_end_date values), or whether that is possible.
精彩评论