У меня есть база данных SQL Server 2000, которая содержит представление, показывающее показания счетчиков для точек снабжения со следующими столбцами:
- 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
Каждая точка снабжения может иметь 0..N показаний. Мне нужно получить последнюю отправленную строку для любого заданного SupplyPoint. И я хочу выполнить это с помощью одного запроса к базе данных.
Мне нужно сделать что-то вроде этого:
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();
На человеческом языке мне нужно выбрать последний ряд каждой группы и вернуть этот ряд. Выполнение этого запроса (или любой другой комбинации, о которой я мог подумать) приведет к следующему:
Для выполнения этого запроса требуется оператор APPLY, который
не поддерживается в версиях SQL Server ранее, чем SQL Server
2005
Мне нужно сделать это в SQL Server 2000.
Это не обязательно должно быть выражение Group By; все, что будет возвращать максимальную строку для данного ключа, будет делать.
Мое решение:
Основываясь на ответе Аарона, я закончил с этим запросом, который делает то, что мне нужно (с предупреждением, но бизнес-правила удаляют его из уравнения для меня).
Предостережение: , если для одних и тех же точек снабжения совпадают даты, сервер sql решит, какую строку выбрать
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();