Quelle est la requête SQL la plus simple pour trouver la deuxième valeur la plus élevée?


168

Quelle est la requête SQL la plus simple pour trouver la deuxième valeur entière la plus grande dans une colonne spécifique?

Il y a peut-être des valeurs en double dans la colonne.


utiliser le décalage à cette fin ... sélectionner l'extension de [dbo]. [Employés] ordre par extension desc offset 2 lignes chercher les 1 lignes suivantes seulement
Jinto John

Réponses:


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

7
La réponse de Matt ainsi que celle de Vinoy s'occupe également des doublons. Supposons que la plus grande valeur soit répétée, puis l'utilisation de la réponse de Matt produira la deuxième valeur la plus élevée correcte, tandis que si vous avez utilisé l' approche des 2 premières desc et min , vous pouvez obtenir la valeur la plus grande à la place.
Pankaj Sharma

Que faire s'il y a plusieurs secondes plus élevées ... Alors cela ne donnera pas tous les tuples
Parth Satra

2
merci, utilisé ceci pour trouver l'avant-dernière date ici
shaijut

Bien mieux que mon approche utilisant ORDER_BY et LIMIT pour la déclaration intérieure
andig

Notez que cela ne retournera pas de résultat s'il n'y a pas d'enregistrements avant celui demandé.
andig

61
SELECT MAX(col) FROM table WHERE col NOT IN (SELECT MAX(col) FROM table);

31

Dans T-Sql, il y a deux façons:

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

Dans Microsoft SQL, la première méthode est deux fois plus rapide que la seconde, même si la colonne en question est groupée.

Cela est dû au fait que l'opération de tri est relativement lente par rapport à l'analyse de table ou d'index utilisée par l' maxagrégation.

Alternativement, dans Microsoft SQL 2005 et supérieur, vous pouvez utiliser la ROW_NUMBER()fonction:

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

20

Je vois ici à la fois des solutions spécifiques à SQL Server et des solutions spécifiques à MySQL, vous voudrez peut-être clarifier la base de données dont vous avez besoin. Cependant, si je devais deviner, je dirais SQL Server car c'est trivial dans MySQL.

Je vois aussi des solutions qui ne fonctionneront pas car elles ne prennent pas en compte la possibilité de doublons, alors faites attention à celles que vous acceptez. Enfin, j'en vois quelques-uns qui fonctionneront mais qui feront deux scans complets de la table. Vous voulez vous assurer que la deuxième analyse ne regarde que 2 valeurs.

SQL Server (avant 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

Mettre à jour:

SQL Server 2012 prend désormais en charge une syntaxe OFFSET / FETCH beaucoup plus propre (et standard ):

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

C'est ce que j'espérais voir. La réponse acceptée devient moche si vous en avez besoin n. Celui-ci résiste à ce test.
Robin Maben

@RobinMaben Robin, qu'en est-il du scénario lorsque la plus grande valeur est répétée? Supposons qu'une colonne contienne les nombres 1 à 100 mais que 100 soit répété deux fois. Ensuite, cette solution produira la deuxième plus grande valeur comme 100, ce qui sera incorrect. Droite?
Pankaj Sharma

1
@PankajSharma non, cela fonctionnera toujours, à cause de la clause GROUP BY
Joel Coehoorn

C'est la manière standard de procéder. La réponse acceptée doit être mise à jour avec celle-ci.
Guilherme Melo

1
J'obtiens une erreur indiquant que je ne peux pas utiliser TOPet OFFSETdans la même requête.
Spurious

15

Je suppose que vous pouvez faire quelque chose comme:

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

ou

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

en fonction de votre serveur de base de données. Astuce: SQL Server ne fait pas LIMIT.


update- SQL Server 2012 a ajouté une clause offset / fetch similaire à la ci-dessus dbadiaries.com
...

Supposons que vous ayez 2 éléments avec la même valeur mais aussi le plus grand élément. Je suppose que vous devez faireOFFSET 2
Kangkan

L'ajout d'une clause GROUP BY répondra à la condition de duplication dans ce cas.
Saif

7

Le plus simple serait d'obtenir la deuxième valeur de ce jeu de résultats dans l'application:

SELECT DISTINCT value FROM Table ORDER BY value DESC LIMIT 2

Mais si vous devez sélectionner la deuxième valeur à l'aide de SQL, que diriez-vous:

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

1
Avez-vous exécuté cela sur SQL Server?
Craig

1
@Craig - LIMITest la syntaxe MySql, la question ne spécifie pas de version SQL.
Keith


4

Une requête très simple pour trouver la deuxième plus grande valeur

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

Pas besoin de sous-requêtes ... il suffit de sauter une ligne et de sélectionner les secondes lignes après l'ordre par ordre décroissant


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

Cette requête renverra le salaire maximum, à partir du résultat - qui ne contient pas le salaire maximum de la table globale.


2
Pouvez-vous modifier pour expliquer en quoi cela est très différent des anciennes réponses?
Nathan Tuggy

3

Ancienne question que je connais, mais cela m'a donné un meilleur plan exécutif:

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

3

C'est du code très simple, vous pouvez essayer ceci: -

ex: nom de la table = test

salary 

1000
1500
1450
7500

Code MSSQL pour obtenir la deuxième plus grande valeur

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

ici 'offset 1 rows' signifie la 2ème ligne du tableau et 'fetch next 1 rows only' est pour afficher uniquement cette 1 ligne. si vous n'utilisez pas «récupérer les 1 lignes suivantes seulement», il affiche toutes les lignes de la deuxième ligne.


Réponse la plus optimisée et la plus conviviale. J'ai gagné beaucoup de temps en l'utilisant dans ma sous-requête. Merci.
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

J'espère que cela vous aidera à obtenir la valeur de n'importe quelle ligne .....


2

Le plus simple de tous

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)

Remarque

sal est le nom de la
colonne emp est le nom de la table


1

Tom, je crois que cela échouera lorsqu'il y aura plus d'une valeur retournée dans la select max([COLUMN_NAME]) from [TABLE_NAME]section. c'est-à-dire où il y a plus de 2 valeurs dans l'ensemble de données.

Une légère modification de votre requête fonctionnera -

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

la sous-requête renvoie toutes les valeurs autres que la plus grande. sélectionnez la valeur maximale dans la liste renvoyée.


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

1

C'est le moyen le plus simple:

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

Comme vous l'avez mentionné, les valeurs en double. Dans ce cas, vous pouvez utiliser DISTINCT et GROUP BY pour trouver la deuxième valeur la plus élevée

Voici un tableau

un salaire

:

entrez la description de l'image ici

PAR GROUPE

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

Première partie de LIMIT = index de départ

Deuxième partie de LIMIT = combien de valeur


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

cela retournera le troisième sal le plus élevé de la table emp


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

not in est une condition qui exclut la valeur la plus élevée de nom_colonne.

Référence: interview de programmeur


0

Quelque chose comme ça? Je ne l'ai pas testé, cependant:

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


0

À l'aide d'une requête corrélée:

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)

Cette requête sélectionne les trois salaires maximum. Si deux emp reçoivent le même salaire, cela n'affecte pas la requête.


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

0

Cela fonctionne dans MS SQL:

select max([COLUMN_NAME]) from [TABLE_NAME] where [COLUMN_NAME] < 
 ( select max([COLUMN_NAME]) from [TABLE_NAME] )
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.