Получить максимальную / минимальную запись - PullRequest
4 голосов
/ 13 июля 2009

Довольно сложный SQL-запрос, над которым я работал, заставил меня задуматься об ограничении (ANSI) SQL:

Есть ли способ извлечь максимальную или минимальную запись по произвольному порядку?

Другими словами:

Задан такой запрос:

SELECT * FROM mytable WHERE <various conditions> ORDER BY <order clause>

возможно ли написать запрос, который возвращает только первую строку (возможно, путем преобразования предложения order во что-то еще)?

Я знаю, что вы можете сделать это, используя LIMIT (MySQL) / ROWNUM (Oracle) или аналогичный, но это не стандартный SQL.

Я также знаю, что вы можете сделать это, выбрав значение max / min, которое вас интересует в подзапросе (используя MIN () / MAX ()), и затем используйте этот результат в качестве критерия в вашем основном SELECT, то есть: 1014 *

SELECT * FROM mytable WHERE <various conditions> AND myMaxColumn=(
  SELECT MAX(myMaxColumn) FROM mytable WHERE <various conditions>
)

Но это работает, только если я хочу отсортировать по одному столбцу. Я не вижу способа обобщить это на несколько столбцов (кроме вложенности вышеуказанного решения, но это будет означать 2 ^ n SELECT при упорядочении по n столбцам).

Так есть ли лучший способ в стандартном SQL, чем вложение нескольких вложенных элементов?

Соответствующий вопрос задается в Создайте запрос SQL для получения самых последних записей . Тем не менее, ответы там предлагают либо использовать LIMIT & friends, либо использовать подзапрос с MAX (), как описано выше, оба из которых не являются решением моего вопроса.

Ответы [ 2 ]

10 голосов
/ 13 июля 2009

SQL:2003 определяет понятие оконных функций, одна из которых:

SELECT  *
FROM    (
        SELECT  *, ROW_NUMBER() OVER (ORDER BY col1, col2, col3) AS rn
        FROM    mytable
        ) q
WHERE   rn = 1

вернет вам эту первую запись.

На данный момент поддерживается SQL Server, Oracle и, начиная с Jul 01, 2009, PostgreSQL 8.4

Обратите внимание, однако, что ROW_NUMBER() в Oracle менее эффективен, чем собственный способ ограничения записей (т.е. ROWNUM).

См. Эту статью в моем блоге для сравнения производительности:

SQL:2008 предлагает еще один пункт для этого:

SELECT  *
FROM    mytable
ORDER BY
        col1, col2, col3
FETCH FIRST 1 ROW ONLY

, но на данный момент этот точный синтаксис поддерживается только DB2 (AFAIK).

8 голосов
/ 13 июля 2009

Если я вас правильно понял, я думаю, вы ищете предложение OVER, которое позволяет разбивать результирующие наборы, определенные как часть ANSI SQL 2003 стандарта.

Он не очень последовательно реализован на платформах RDBMS.

...