Можно ли сделать GROUP BY в SQL Server 2000, который возвращает всю строку? - PullRequest
0 голосов
/ 07 сентября 2011

У меня есть база данных 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();

1 Ответ

1 голос
/ 07 сентября 2011

Я абсолютно не знаю, как написать это в linq-to-entity, но вот общая методология в прямом T-SQL (при условии, что rh_sp_number - это столбец, по которому вы хотите сгруппировать).

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;

Обратите внимание, что вы не указываете, что делать со связями (две строки с одинаковыми значениями rh_sp_number и rh_end_date), или это возможно.

...