У меня есть простой запрос, и задаюсь вопросом, мог ли он быть более изящно кодирован. Конечное решение должно быть ansi-совместимым.
Я должен выбрать последнее значение от таблицы на основе даты и версии. Образец объяснил бы более ясно:
declare @t table (id int, due_date smalldatetime, version int, value nvarchar(10))
insert into @t select 3, '1/1/2010', 1, 'value 1'
insert into @t select 3, '1/1/2010', 2, 'value 2'
insert into @t select 3, '3/1/2010', 1, 'value 3'
insert into @t select 3, '3/1/2010', 2, 'value 4'
insert into @t select 3, '3/1/2010', 3, 'value 5'
insert into @t select 3, '3/1/2010', 4, 'value 6'
insert into @t select 3, '4/1/2010', 1, 'value 7'
insert into @t select 3, '4/1/2010', 2, 'value 8'
insert into @t select 3, '4/1/2010', 3, 'value 9'
select value from @t t
inner join (select due_date, version=max(version)
from @t where due_date = (select max(due_date) from @t) group by due_date) maxes
on t.due_date=maxes.due_date and t.version=maxes.version
Таким образом, я ожидал бы, что вывод будет
value 9
который это на основе вышеупомянутого запроса.
Я не особенно доволен этим решением - какие-либо лучшие способы выполнить это?
Вы можете использовать:
SELECT TOP 1
x.value
FROM @t x
ORDER BY x.due_date DESC, x.version DESC
Однако TOP не является ANSI. Другим вариантом было бы использование аналитических/ранговых/оконных функций ANSI:
SELECT x.value
FROM (SELECT t.value,
ROW_NUMBER() OVER (ORDER BY t.due_date DESC, t.version DESC) AS rank
FROM @t t) x
WHERE x.rank = 1
Но для этого требуется база данных, которая поддерживает эту функциональность - MySQL не поддерживает, PostgreSQL начал только в версии 8.4...
SELECT
value
FROM
@t T1
LEFT OUTER JOIN @t T2 ON
T2.id = T1.id AND
(
(T2.due_date > T1.due_date) OR
(T2.due_date = T1.due_date AND T2.version > T1.version)
)
WHERE
T2.id IS NULL
или...
SELECT
value
FROM
@t T1
WHERE
NOT EXISTS
(
SELECT
FROM
@t T2
WHERE
T2.id = T1.id AND
(
(T2.due_date > T1.due_date) OR
(T2.due_date = T1.due_date AND T2.version > T1.version)
)
)