Оператор SQL для выбора значения последней версии данных на основе последней даты - PullRequest
5 голосов
/ 07 июля 2010

У меня есть простой запрос, и мне интересно, может ли он быть более элегантно закодирован. Окончательное решение должно соответствовать требованиям.

Мне нужно получить последнее значение из таблицы на основе даты и версии. Образец объяснил бы более четко:

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

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

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

Ответы [ 2 ]

5 голосов
/ 07 июля 2010

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

  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 только запущен в v8.4 ...

1 голос
/ 07 июля 2010
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)
            )
    )
...