[MSSQL] Агрегаты FIRST и LAST
От: _FRED_ Россия
Дата: 15.10.10 13:59
Оценка:
Имеется некая табличка, к которой обращаются с запросами. В запросах имееюся некая группировка и выборка значений. Например:

CREATE TABLE [#T] (
  [Number] int,
  [DateTime] datetime,
  [Value] nchar,
);

INSERT [#T] ([Number], [DateTime], [Value]) VALUES (1, N'2010-01-01', N'D');
INSERT [#T] ([Number], [DateTime], [Value]) VALUES (1, N'2010-01-01', N'E');
INSERT [#T] ([Number], [DateTime], [Value]) VALUES (1, N'2010-01-02', N'A');
INSERT [#T] ([Number], [DateTime], [Value]) VALUES (1, N'2010-01-03', N'B');
INSERT [#T] ([Number], [DateTime], [Value]) VALUES (1, N'2010-01-03', N'C');
INSERT [#T] ([Number], [DateTime], [Value]) VALUES (1, N'2010-02-01', N'3');
INSERT [#T] ([Number], [DateTime], [Value]) VALUES (1, N'2010-02-01', N'2');
INSERT [#T] ([Number], [DateTime], [Value]) VALUES (1, N'2010-02-02', N'1');
INSERT [#T] ([Number], [DateTime], [Value]) VALUES (1, N'2010-02-03', N'4');
INSERT [#T] ([Number], [DateTime], [Value]) VALUES (1, N'2010-02-03', N'5');
INSERT [#T] ([Number], [DateTime], [Value]) VALUES (2, N'2010-01-01', N'U');
INSERT [#T] ([Number], [DateTime], [Value]) VALUES (2, N'2010-01-01', N'V');
INSERT [#T] ([Number], [DateTime], [Value]) VALUES (2, N'2010-01-02', N'X');
INSERT [#T] ([Number], [DateTime], [Value]) VALUES (2, N'2010-01-03', N'Z');
INSERT [#T] ([Number], [DateTime], [Value]) VALUES (2, N'2010-01-03', N'Y');

SELECT [Number], MONTH([DateTime]) [Month], MIN([Value]) [Value]
FROM [#T]
GROUP BY [Number], MONTH([DateTime]);

DROP TABLE [#T];

Результат:
Number  Month   Value
1       1       A
2       1       U
1       2       1


Требуется уметь считать по [Value] не только стандартные COUNT/AVG/SUM/MIN/MAX но, например, и FIRST и LAST — то есть в пределах группы требуется найти строку с минимальным или максимальным значением [DateTime] и вернуть значение [Value] этой строки.

У меня вышло как-то сложновато:
SELECT T.[Number], T.[Month], X.[Value]
FROM (SELECT [Number], MONTH([DateTime]) [Month], MIN([DateTime]) [Order] FROM [#T] GROUP BY [Number], MONTH([DateTime])) T
JOIN (SELECT [Number], [DateTime] [Order], MIN([Value]) [Value] FROM [#T] GROUP BY [Number], [DateTime]) X
  ON X.[Number] = T.[Number] AND T.[Order] = X.[Order];

Number  Month   Value
1       1       D
1       2       2
2       1       U


В реальности количество строк в таблице — несколько миллионов. Агрегаты над [DateTime] не просто MONTH() а немного более хитрые вычисления (Начало/конец года, например). Смущает необходимость дважды считать группы.

Может ли кто подсказать, как можно упростить второй запрос или, вообще, решить задачу другим, более правильным способом?
Help will always be given at Hogwarts to those who ask for it.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.