Выбрать все строки, но только самую последнюю (самую высокую) версию из базы данных

Я хочу получить все строки из БД, где OWNERKEY 1, но только самый высокий DATAVERSION из DATACONTROLID,

В приведенном ниже примере у меня есть две строки, где DATACONTROLID= 1, они имеют 1 и 2 как DATAVERSION, Я хочу получить самое высокое.

MyDB:

DATAKEY       OWNERKEY       OWNERTYPE      DATAVERSION   MALLKEY       DATAVALUE    DATAVALUETYPE   DATACONTROLID   DATADATE     DATATIME      DATASIGN
===========   ============   ===========   ===========   ===========   =========    ============    =============   ==========   ===========   =========     
4              1             2             1             1             1             2                1             2015-11-24   09:55:00:00   ADMIN
3              1             2             2             1             2             2                1             2015-11-23   20:55:00:00   ADMIN
2              1             2             1             1             3             2                2             2015-11-23   15:39:00:00   ADMIN
1              1             2             1             1             4             2                3             2015-11-23   11:29:00:00   ADMIN

Требуемый результат:

DATAKEY       OWNERKEY       OWNERTYPE      DATAVERSION   MALLKEY       DATAVALUE    DATAVALUETYPE   DATACONTROLID   DATADATE     DATATIME      DATASIGN
===========   ============   ===========   ===========   ===========   =========    ============    =============   ==========   ===========   =========     
3              1             2             2             1             2             2                1             2015-11-23   20:55:00:00   ADMIN
2              1             2             1             1             3             2                2             2015-11-23   15:39:00:00   ADMIN
1              1             2             1             1             4             2                3             2015-11-23   11:29:00:00   ADMIN

С чего мне начать?

SELECT *
FROM MyDB
WHERE OWNERKEY = 1

Вышеприведенное утверждение является частью obviuos, но как мне исходить из этого?

Я думаю, что я должен использовать MAX(DATAVERSION) как-то, но на что группировать? И могу ли я использовать оба * а также MAX?

3 ответа

Решение

Вот простой пример использования GROUP BY в MSSQL:

SELECT  DATACONTROLID, 
        MAX(DATAVERSION) AS DATAVERSION, -- Note that 'AS' just gives the column a name in the result set, this isn't required.
        OWNERKEY
FROM    MyDB
WHERE   OWNERKEY = 1
GROUP BY DATACONTROLID, OWNERKEY

Это при условии, что DATACONTROLID определяет "отдельные" записи и DATAVERSION это экземпляр записи.

Это сгруппирует DATACONTROLID столбец и вернуть MAX(DATAVERSION) для сгруппированного результата. В этом случае, DATACONTROLID = 1 имеет DATAVERSION = 1 and 2, так что это возвращает 2.

Стоит отметить, что если вы хотите видеть дополнительные столбцы в вашем результате, а они не являются такими агрегатами, какMAX(), то вам нужно будет добавить их в GROUP BY пункт - как я сделал здесь с OWNERKEY колонка. Если вы попытаетесь SELECT OWNERKEY не имея его в GROUP BY, вы получите ошибку.

РЕДАКТИРОВАТЬ:

Вот лучший способ добиться того же результата, используя JOIN:

SELECT  *
FROM    MyDB mdb
INNER JOIN (
    SELECT  MAX(DATAVERSION) AS DATAVERSION,
            DATACONTROLID
    FROM    MyDB
    WHERE   OWNERKEY = 1
    GROUP BY DATACONTROLID
) AS mdb2 
    ON  mdb2.DATACONTROLID = mdb.DATACONTROLID 
        AND mdb2.DATAVERSION = mdb.DATAVERSION

Это делает то же самое GROUP BY Заявление, которое я показал вам раньше, в таблицу фильтрации. INNER JOIN часть выбирает MAX(DATAVERSION) и DATACONTROLID он принадлежит и возвращает результат как временную таблицу mdb2,

Эта новая внутренняя таблица вернет следующее:

DATAVERSION DATACONTROLID
2           1
1           2
1           3

Затем мы берем этот результат и получаем все строки (SELECT *) которые соответствуют этому критерию. Поскольку эта внутренняя таблица не содержит результат для DATAVERSION = 1 where DATACONTROLID = 1этот ряд отфильтровывается.

И наоборот, если вы хотите видеть только старые версии, а не самые новые, вы можете изменить этот критерий на LEFT OUTER JOIN и добавить WHERE mdb2.DATAVERSION IS NULL,

SELECT  *
FROM    MyDB mdb
LEFT OUTER JOIN (
    SELECT  MAX(DATAVERSION) AS DATAVERSION,
            DATACONTROLID
    FROM    MyDB
    WHERE   OWNERKEY = 1
    GROUP BY DATACONTROLID
) AS mdb2 
    ON  mdb2.DATACONTROLID = mdb.DATACONTROLID 
        AND mdb2.DATAVERSION = mdb.DATAVERSION
WHERE mdb2.DATAVERSION IS NULL

Так как мы выбираем MAX(DATAVERSION) в mdb2, он будет содержать ноль для строк, которые не соответствуют этим критериям.

Попробуй это:

SELECT *
  FROM (SELECT OWNERKEY,DATACONTROLID,DATAVERSION,
               rank() over (partition by DATACONTROLID order by DATAVERSION desc) rnk
          FROM MyDB WHERE OWNERKEY = 1)
 WHERE rnk = 1;

Примечание: я не проверял, но это должно работать

Как насчет

SELECT *
FROM MyDB
WHERE OWNERKEY = 1
and   DATAVERSION = 
      (SELECT max(DATAVERSION)
      FROM MyDB
      WHERE OWNERKEY = 1)

Это работает в некоторых средах баз данных; Я надеюсь, что ваш! Я узнал об этом из "Введение в SQL, освоение языка реляционных баз данных" Рика Ф. ван дер Ланса. Довольно легко читать.

Другие вопросы по тегам