¿Cuál es la consulta SQL más simple para encontrar el segundo valor más grande?

168

¿Cuál es la consulta SQL más simple para encontrar el segundo valor entero más grande en una columna específica?

Quizás haya valores duplicados en la columna.

Niyaz
fuente
use offset para este propósito ... seleccione la extensión de [dbo]. [Empleados] ordene por extensión desc offset 2 filas busque las siguientes 1 filas solamente
Jinto John

Respuestas:

295
SELECT MAX( col )
  FROM table
 WHERE col < ( SELECT MAX( col )
                 FROM table )
Matt Rogish
fuente
77
La respuesta de Matt y de Vinoy también se ocupa de los duplicados. Suponga que el valor más grande se repite y luego usar la respuesta de Matt producirá el segundo valor más grande correcto, mientras que si usó el enfoque 2 desc y min más alto , puede obtener el valor más grande.
Pankaj Sharma
¿Qué pasa si hay varios segundos más altos ... Entonces esto no dará todas las Tuplas
Parth Satra
2
gracias, usé esto para encontrar la segunda última cita aquí
shaijut
Mucho mejor que mi enfoque usando ORDER_BY y LIMIT para la declaración interna
andig
Tenga en cuenta que esto no devolverá un resultado si no hay registros anteriores al solicitado.
andig
61
SELECT MAX(col) FROM table WHERE col NOT IN (SELECT MAX(col) FROM table);
Vinoy
fuente
31

En T-Sql hay dos formas:

--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 

En Microsoft SQL, la primera forma es dos veces más rápida que la segunda, incluso si la columna en cuestión está agrupada.

Esto se debe a que la operación de clasificación es relativamente lenta en comparación con la exploración de tabla o índice que el max utiliza agregación.

Alternativamente, en Microsoft SQL 2005 y superior puede usar la ROW_NUMBER()función:

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

Veo algunas soluciones específicas de SQL Server y algunas específicas de MySQL aquí, por lo que es posible que desee aclarar qué base de datos necesita. Aunque si tuviera que adivinar, diría SQL Server ya que esto es trivial en MySQL.

También veo algunas soluciones que no funcionarán porque no tienen en cuenta la posibilidad de duplicados, así que tenga cuidado con las que acepta. Finalmente, veo algunos que funcionarán pero que harán dos escaneos completos de la tabla. Desea asegurarse de que la segunda exploración solo busque 2 valores.

SQL Server (anterior a 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

Actualizar:

SQL Server 2012 ahora admite una sintaxis OFFSET / FETCH mucho más limpia (y estándar ):

SELECT TOP 2 [column] 
FROM [Table] 
GROUP BY [column] 
ORDER BY [column] DESC
OFFSET 1 ROWS
FETCH NEXT 1 ROWS ONLY;
Joel Coehoorn
fuente
Esto es lo que esperaba ver. La respuesta aceptada se vuelve fea si necesita que funcione para cualquiera n. Este resiste esa prueba.
Robin Maben
@ Robin Robin, ¿qué tal el escenario cuando se repite el valor más grande? Suponga que una columna contiene números del 1 al 100 pero 100 se repite dos veces. Entonces esta solución producirá el segundo valor más grande como 100, que será incorrecto. ¿Correcto?
Pankaj Sharma
1
@PankajSharma no, esto seguirá funcionando, debido a la cláusula GROUP BY
Joel Coehoorn el
Esta es la forma estándar de hacer esto. La respuesta aceptada debe actualizarse a esta.
Guilherme Melo
1
Recibo un error que dice que no puedo usar TOPy OFFSETen la misma consulta.
Espurio el
15

Supongo que puedes hacer algo como:

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

o

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

dependiendo de su servidor de base de datos. Sugerencia: SQL Server no hace LIMIT.

dguaraglia
fuente
actualización: SQL Server 2012 agregó una cláusula de desplazamiento / recuperación similar a la anterior dbadiaries.com/…
iliketocode
Suponga que tiene 2 elementos con el mismo valor pero también el elemento más grande. Supongo que tienes que hacerOFFSET 2
Kangkan
Agregar la cláusula GROUP BY atenderá la condición duplicada en esto.
Saif
7

Lo más fácil sería obtener el segundo valor de este conjunto de resultados en la aplicación:

SELECT DISTINCT value FROM Table ORDER BY value DESC LIMIT 2

Pero si debe seleccionar el segundo valor usando SQL, ¿qué tal:

SELECT MIN(value) FROM (SELECT DISTINCT value FROM Table ORDER BY value DESC LIMIT 2) AS t
Magnar
fuente
1
¿Has ejecutado esto en SQL Server?
Craig
1
@Craig: LIMITes la sintaxis de MySql , la pregunta no especifica una versión de SQL.
Keith
4

Una consulta muy simple para encontrar el segundo valor más grande

SELECT `Column` FROM `Table` ORDER BY `Column` DESC LIMIT 1,1;
pequeño
fuente
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

No es necesario realizar subconsultas ... solo omita una fila y seleccione las segundas filas después del pedido descendiendo

Justin jose
fuente
3
SELECT MAX(Salary) FROM Employee WHERE Salary NOT IN (SELECT MAX(Salary) FROM Employee )

Esta consulta devolverá el salario máximo del resultado, que no contiene el salario máximo de la tabla general.

Naresh Kumar
fuente
2
¿Puedes editar para explicar cómo esto es significativamente diferente de las respuestas anteriores?
Nathan Tuggy
3

Antigua pregunta que conozco, pero esto me dio un mejor plan ejecutivo:

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

Este es un código muy simple, puedes probar esto: -

Ej: nombre de tabla = prueba

salary 

1000
1500
1450
7500

Código MSSQL para obtener el segundo valor más grande

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

aquí 'desplazar 1 filas' significa la segunda fila de la tabla y 'buscar las siguientes 1 filas solamente' es para mostrar solo esa 1 fila. si no utiliza 'buscar solo las siguientes 1 filas', muestra todas las filas de la segunda fila.

Nijish
fuente
La respuesta más optimizada y amigable con los recursos. Ahorré bastante tiempo usándolo en mi subconsulta. Gracias.
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

Espero que esta ayuda obtenga el valor de cualquier fila .....

Rohit Singh
fuente
2

Más simple de todos

select sal from salary order by sal desc limit 1 offset 1
sumeet
fuente
1
select min(sal) from emp where sal in 
    (select TOP 2 (sal) from emp order by sal desc)

Nota

sal es col nombre
emp es nombre de tabla

Ni3
fuente
1

Tom, cree que esto fallará cuando haya más de un valor devuelto en la select max([COLUMN_NAME]) from [TABLE_NAME]sección. es decir, donde hay más de 2 valores en el conjunto de datos.

Una ligera modificación a su consulta funcionará:

select max([COLUMN_NAME]) from [TABLE_NAME] where [COLUMN_NAME] **IN** 
  ( select max([COLUMN_NAME]) from [TABLE_NAME] )
sunith
fuente
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));

La subconsulta devuelve todos los valores que no sean los más grandes. seleccione el valor máximo de la lista devuelta.

sunith
fuente
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
fuente
1
SELECT 
    * 
FROM 
    table 
WHERE 
    column < (SELECT max(columnq) FROM table) 
ORDER BY 
    column DESC LIMIT 1
gorriones avie
fuente
1

Es la forma más fácil:

SELECT
      Column name
FROM
      Table name 
ORDER BY 
      Column name DESC
LIMIT 1,1
Ravind Maurya
fuente
1
select age from student group by id having age<(select max(age) from student)order by age limit 1
PUNTO MUERTO
fuente
1

Como mencionaste valores duplicados. En tal caso, puede usar DISTINCT y GROUP BY para encontrar el segundo valor más alto

Aqui hay una mesa

salario

:

ingrese la descripción de la imagen aquí

AGRUPAR POR

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

DISTINTO

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

Primera porción de LIMIT = índice inicial

Segunda porción de LIMIT = cuántos valores

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

esto devolverá la tercera tabla más alta de sal de emp

Swadesh
fuente
1
select max(column_name) from table_name
where column_name not in (select max(column_name) from table_name);

no en es una condición que excluye el valor más alto de column_name.

Referencia: entrevista al programador

rashedcs
fuente
0

¿Algo como esto? Sin embargo, no lo he probado:

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

Usando una consulta correlacionada:

Select * from x x1 where 1 = (select count(*) from x where x1.a < a)
algo
fuente
0
select * from emp e where 3>=(select count(distinct salary)
    from emp where s.salary<=salary)

Esta consulta selecciona los tres salarios máximos. Si dos emp obtienen el mismo salario, esto no afecta la consulta.

algo
fuente
0
select top 1 MyIntColumn from MyTable
where
 MyIntColumn <> (select top 1 MyIntColumn from MyTable order by MyIntColumn desc)
order by MyIntColumn desc
Chris Conway
fuente
0

Esto funciona en MS SQL:

select max([COLUMN_NAME]) from [TABLE_NAME] where [COLUMN_NAME] < 
 ( select max([COLUMN_NAME]) from [TABLE_NAME] )
Tom Welch
fuente