Какой самый простой 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
61
SELECT MAX(col) FROM table WHERE col NOT IN (SELECT MAX(col) FROM table);
Вина
источник
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.

dguaraglia
источник
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
Magnar
источник
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

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

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

SELECT `Column` FROM `Table` ORDER BY `Column` DESC LIMIT 1,1;
petcy
источник
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
Dier
источник
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 строки», тогда будут показаны все строки из второй строки.

Nijish.
источник
Наиболее оптимизированный и дружественный к ресурсам ответ. Я сэкономил довольно много времени, используя его в своем подзапросе. Спасибо.
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
Sumeet
источник
1
select min(sal) from emp where sal in 
    (select TOP 2 (sal) from emp order by sal desc)

Заметка

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

Ni3
источник
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] )
sunith
источник
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));

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

sunith
источник
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
Divya.NR
источник
1
SELECT 
    * 
FROM 
    table 
WHERE 
    column < (SELECT max(columnq) FROM table) 
ORDER BY 
    column DESC LIMIT 1
ави воробьи
источник
1

Это самый сложный способ:

SELECT
      Column name
FROM
      Table name 
ORDER BY 
      Column name DESC
LIMIT 1,1
Равинд Маурья
источник
1
select age from student group by id having age<(select max(age) from student)order by age limit 1
ТУПИК
источник
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

Swadesh
источник
1
select max(column_name) from table_name
where column_name not in (select max(column_name) from table_name);

not in - это условие, которое исключает наибольшее значение column_name.

Ссылка: интервью с программистом

rashedcs
источник
0

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

select top 1 x
from (
  select top 2 distinct x 
  from y 
  order by x desc
) z
order by x
doekman
источник
0

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

Select * from x x1 where 1 = (select count(*) from x where x1.a < a)
STH
источник
0
select * from emp e where 3>=(select count(distinct salary)
    from emp where s.salary<=salary)

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

STH
источник
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] )
Том Уэлч
источник