SQL-оператор для выбора значения последней версии данных на основе последней даты

У меня есть простой запрос, и задаюсь вопросом, мог ли он быть более изящно кодирован. Конечное решение должно быть 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

который это на основе вышеупомянутого запроса.

Я не особенно доволен этим решением - какие-либо лучшие способы выполнить это?

5
задан Deduplicator 24 February 2015 в 01:56
поделиться

2 ответа

Вы можете использовать:

  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...

5
ответ дан 14 December 2019 в 13:25
поделиться
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)
            )
    )
1
ответ дан 14 December 2019 в 13:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: