Какой самый простой SQL-запрос для поиска второго по величине значения?


168

Какой самый простой SQL-запрос для поиска второго по величине целочисленного значения в определенном столбце?

Возможно, в столбце есть повторяющиеся значения.


используйте смещение для этой цели ... выберите расширение из [dbo]. Порядок [Сотрудники] по расширению desc смещение 2 строки выбирают только следующие 1 строки
Jinto John

Ответы:


295
SELECT MAX( col )
  FROM table
 WHERE col < ( SELECT MAX( col )
                 FROM table )

7
Ответ Мэтта, а также ответа Виной заботится о дубликатах. Предположим, что наибольшее значение повторяется, а затем, используя ответ Мэтта, получится правильное второе по величине значение, в то время как, если вы использовали подход 2 верхних и минимальных значений, вы можете получить наибольшее значение.
Панкадж Шарма

Что если есть несколько секунд наивысшего ... Тогда это не даст всем кортежам
Parth Satra

2
спасибо, использовал это, чтобы найти второе последнее свидание здесь
shaijut

Намного лучше, чем мой подход, использующий ORDER_BY и LIMIT для внутреннего утверждения
andig

Обратите внимание, что это не вернет результат, если нет записей до запрошенной.
Andig


31

В T-Sql есть два способа:

--filter out the max
select max( col )
from [table]
where col < ( 
    select max( col )
    from [table] )

--sort top two then bottom one
select top 1 col 
from (
    select top 2 col 
    from [table]
    order by col) topTwo
order by col desc 

В Microsoft SQL первый способ в два раза быстрее второго, даже если рассматриваемый столбец кластеризован.

Это связано с тем, что операция сортировки выполняется относительно медленно по сравнению со сканированием таблицы или индекса, которое maxиспользует агрегация.

В качестве альтернативы, в Microsoft SQL 2005 и выше вы можете использовать ROW_NUMBER()функцию:

select col
from (
    select ROW_NUMBER() over (order by col asc) as 'rowNum', col
    from [table] ) withRowNum 
where rowNum = 2

20

Я вижу как некоторые специфичные для SQL Server, так и некоторые специфичные для MySQL решения, поэтому вы можете уточнить, какая база данных вам нужна. Хотя, если бы мне пришлось угадывать, я бы сказал, что SQL Server, поскольку в MySQL это тривиально.

Я также вижу некоторые решения, которые не будут работать, потому что они не учитывают возможность дублирования, поэтому будьте осторожны, какие из них вы принимаете. Наконец, я вижу несколько, которые будут работать, но это сделает два полных сканирования таблицы. Вы хотите убедиться, что второе сканирование просматривает только 2 значения.

SQL Server (до 2012 года):

SELECT MIN([column]) AS [column]
FROM (
    SELECT TOP 2 [column] 
    FROM [Table] 
    GROUP BY [column] 
    ORDER BY [column] DESC
) a

MySQL:

SELECT `column` 
FROM `table` 
GROUP BY `column` 
ORDER BY `column` DESC 
LIMIT 1,1

Обновить:

SQL Server 2012 теперь поддерживает намного более чистый (и стандартный ) синтаксис OFFSET / FETCH:

SELECT TOP 2 [column] 
FROM [Table] 
GROUP BY [column] 
ORDER BY [column] DESC
OFFSET 1 ROWS
FETCH NEXT 1 ROWS ONLY;

Это то, что я надеялся увидеть. Принятый ответ становится уродливым, если вам нужно, чтобы он работал для любого n. Этот выдерживает этот тест.
Робин Мабен

@RobinMaben Робин, как насчет сценария, когда наибольшее значение повторяется? Предположим, что столбец содержит числа от 1 до 100, но 100 повторяется дважды. Тогда это решение выдаст второе по величине значение как 100, что будет неверным. Правильно?
Панкадж Шарма

1
@PankajSharma нет, это все еще будет работать, из-за предложения GROUP BY
Джоэль Коухорн

Это стандартный способ сделать это. Принятый ответ должен быть обновлен до этого.
Гильерме Мело

1
Я получаю ошибку, которая говорит, что я не могу использовать TOPи OFFSETв том же запросе.
Ложный

15

Я полагаю, вы можете сделать что-то вроде:

SELECT * FROM Table ORDER BY NumericalColumn DESC LIMIT 1 OFFSET 1

или

SELECT * FROM Table ORDER BY NumericalColumn DESC LIMIT (1, 1)

в зависимости от вашего сервера базы данных. Подсказка: SQL Server не выполняет LIMIT.


update- SQL Server 2012 добавил предложение смещения / выборки, подобное приведенному выше dbadiaries.com/…
iliketocode

Предположим, у вас есть 2 элемента с одинаковым значением, но также с самым большим элементом. Я думаю, вы должны сделатьOFFSET 2
Кангкан

Добавление предложения GROUP BY обслужит дублирующее условие в этом.
Saif

7

Проще всего было бы получить второе значение из этого набора результатов в приложении:

SELECT DISTINCT value FROM Table ORDER BY value DESC LIMIT 2

Но если вам нужно выбрать второе значение с помощью SQL, как насчет:

SELECT MIN(value) FROM (SELECT DISTINCT value FROM Table ORDER BY value DESC LIMIT 2) AS t

1
Вы запускаете это на SQL Server?
Крейг

1
@Craig - LIMITэто синтаксис MySql, вопрос не указывает версию SQL.
Кит

7

Вы можете найти второе по величине значение столбца, используя следующий запрос

SELECT *
FROM TableName a
WHERE
  2 = (SELECT count(DISTINCT(b.ColumnName))
       FROM TableName b WHERE
       a.ColumnName <= b.ColumnName);

Вы можете найти более подробную информацию по следующей ссылке

http://www.abhishekbpatel.com/2012/12/how-to-get-nth-maximum-and-minimun.html


Архив мертвой ссылки: web.archive.org/web/20130406161645/http://…
xgMz

4

Очень простой запрос, чтобы найти второе по величине значение

SELECT `Column` FROM `Table` ORDER BY `Column` DESC LIMIT 1,1;

4

MSSQL

SELECT  *
  FROM [Users]
    order by UserId desc OFFSET 1 ROW 
FETCH NEXT 1 ROW ONLY;

MySQL

SELECT  *
  FROM Users
    order by UserId desc LIMIT 1 OFFSET 1

Нет необходимости в подзапросах ... просто пропустите одну строку и выберите вторые строки после заказа по убыванию


3
SELECT MAX(Salary) FROM Employee WHERE Salary NOT IN (SELECT MAX(Salary) FROM Employee )

Этот запрос вернет максимальный оклад из результата, который не содержит максимальный оклад из общей таблицы.


2
Можете ли вы отредактировать, чтобы объяснить, как это значительно отличается от старых ответов?
Натан Тагги

3

Старый вопрос, который я знаю, но это дало мне лучший план для исполнительной власти:

 SELECT TOP 1 LEAD(MAX (column)) OVER (ORDER BY column desc)
 FROM TABLE 
 GROUP BY column

3

Это очень простой код, вы можете попробовать это: -

пример: имя таблицы = тест

salary 

1000
1500
1450
7500

Код MSSQL для получения второго по величине значения

select salary from test order by salary desc offset 1 rows fetch next 1 rows only;

здесь 'смещение 1 строки' означает 2-ю строку таблицы, а 'выборка только для следующих 1 строки' - для показа только этой 1 строки. если вы не используете «извлечь только следующие 1 строки», тогда будут показаны все строки из второй строки.


Наиболее оптимизированный и дружественный к ресурсам ответ. Я сэкономил довольно много времени, используя его в своем подзапросе. Спасибо.
Vibs2006

2

select * from (select ROW_NUMBER() over (Order by Col_x desc) as Row, Col_1
    from table_1)as table_new tn inner join table_1 t1
    on tn.col_1 = t1.col_1
where row = 2

Надеюсь, что это поможет получить значение для любой строки .....


2

Самый простой из всех

select sal from salary order by sal desc limit 1 offset 1

1
select min(sal) from emp where sal in 
    (select TOP 2 (sal) from emp order by sal desc)

Заметка

sal - имя
столбца emp - имя таблицы


1

Том, поверь, это не удастся, если в select max([COLUMN_NAME]) from [TABLE_NAME]разделе будет возвращено более одного значения . то есть где в наборе данных более 2 значений.

Небольшая модификация вашего запроса будет работать -

select max([COLUMN_NAME]) from [TABLE_NAME] where [COLUMN_NAME] **IN** 
  ( select max([COLUMN_NAME]) from [TABLE_NAME] )

1
select max(COL_NAME) from TABLE_NAME where COL_NAME in 
    (select COL_NAME from TABLE_NAME where COL_NAME < (select max(COL_NAME) from TABLE_NAME));

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


1
select col_name
from (
    select dense_rank() over (order by col_name desc) as 'rank', col_name
    from table_name ) withrank 
where rank = 2




1

Как вы упомянули повторяющиеся значения. В таком случае вы можете использовать DISTINCT и GROUP BY чтобы найти второе по величине значение

Вот таблица

зарплата

:

введите описание изображения здесь

ГРУППА ПО

SELECT  amount FROM  salary 
GROUP by amount
ORDER BY  amount DESC 
LIMIT 1 , 1

DISTINCT

SELECT DISTINCT amount
FROM  salary 
ORDER BY  amount DESC 
LIMIT 1 , 1

Первая часть LIMIT = начальный индекс

Вторая часть LIMIT = сколько стоит


1
SELECT MAX(sal) FROM emp
WHERE sal NOT IN (SELECT top 3 sal FROM emp order by sal desc )

это вернет третье место в таблице emp



0

Что-то вроде этого? Я не проверял это, хотя:

select top 1 x
from (
  select top 2 distinct x 
  from y 
  order by x desc
) z
order by x


0

Используя коррелированный запрос:

Select * from x x1 where 1 = (select count(*) from x where x1.a < a)

0
select * from emp e where 3>=(select count(distinct salary)
    from emp where s.salary<=salary)

Этот запрос выбирает максимум три зарплаты. Если два emp получают одинаковую зарплату, это не влияет на запрос.


0
select top 1 MyIntColumn from MyTable
where
 MyIntColumn <> (select top 1 MyIntColumn from MyTable order by MyIntColumn desc)
order by MyIntColumn desc

0

Это работает в MS SQL:

select max([COLUMN_NAME]) from [TABLE_NAME] where [COLUMN_NAME] < 
 ( select max([COLUMN_NAME]) from [TABLE_NAME] )
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.