2015-11-24 4 views
2

Я хочу получить все строки из БД, где OWNERKEY равен 1, но только самый высокий DATAVERSIONDATACONTROLID.Выберите все строки, но только самую последнюю (самую высокую) версию из базы данных

В приведенном ниже примере у меня есть два ряда, где 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 

Wanted результат:

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?

+0

Max функция возможно? http://www.w3schools.com/sql/sql_func_max.asp имеет некоторые примечания, которые могут быть полезны при условии совместимости SQL. –

+0

Я думаю, вы пропустили мое редактирование. Во всяком случае, могу ли я использовать как *, так и MAX() в инструкции? – Mangs

+0

Да, на ссылке «Попробуйте сами» из моего предыдущего комментария вот запрос, который имеет оба: «SELECT MAX (Price) AS HighestPrice, * FROM Products group by ProductID;' –

ответ

2

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

EDIT:

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

+0

. Это близко к результату. Однако я хочу выбрать все строки. Возможно ли это в этом решении? – Mangs

+0

@JohanMagnusson Я обновил ответ, чтобы отразить это. Надеюсь, поможет! – levelonehuman

+0

Большое вам спасибо за помощь и все объяснения в ответ! – Mangs

2

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

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

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

+0

Я смущен. Можете ли вы дать мне какое-нибудь объяснение, пожалуйста? Что такое rank() и rnk? Спасибо – Mangs

+0

Это функция окна (https://en.wikipedia.org/wiki/Select_%28SQL%29#Window_function) в sql-стандарте sql-2003 – Thierry

+0

Конечно. Что делает ранг, так это то, что он упорядочивает и упорядочивает данные по определенным полям. Поэтому в этом случае мы инструктируем разбивать данные на DATACONTROLID, затем для каждого раздела сортировать данные по DATAVERSION по убыванию и выводить, как запись входит в число всех других записей в этом разделе. Поскольку вы хотите только самую высокую DATAVERSION, нас интересует только то, когда ранг равен 1 (самый высокий, так как мы заказывали desc). И вот что мы делаем, обертывая выбор и фильтрацию, где rnk = 1. – carlosb

0

Как насчет

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

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

+0

Проблема с этим запросом заключается в том, что он вернет одну строку только с тех пор, как вам не хватает группы по предложению –