Was ist die einfachste SQL-Abfrage, um den zweitgrößten Wert zu finden?

168

Was ist die einfachste SQL-Abfrage, um den zweitgrößten ganzzahligen Wert in einer bestimmten Spalte zu finden?

Die Spalte enthält möglicherweise doppelte Werte.

Niyaz
quelle
Verwenden Sie den Offset für diesen Zweck ... wählen Sie die Erweiterung aus [dbo]. [Mitarbeiter] Reihenfolge nach Erweiterung absteigend 2 Zeilen holen nur die nächsten 1 Zeilen ab
Jinto John

Antworten:

294
SELECT MAX( col )
  FROM table
 WHERE col < ( SELECT MAX( col )
                 FROM table )
Matt Rogish
quelle
7
Die Antwort von Matt und Vinoy kümmert sich auch um Duplikate. Angenommen, der größte Wert wird wiederholt, dann ergibt die Verwendung von Matts Antwort den richtigen zweitgrößten Wert. Wenn Sie den Top-2-Desc- und Min- Ansatz verwendet haben, erhalten Sie möglicherweise stattdessen den größten Wert.
Pankaj Sharma
Was ist, wenn es mehrere zweithöchste gibt ... Dann gibt dies nicht alle Tupel
Parth Satra
2
danke, benutzte dies, um hier das
shaijut
Viel besser als mein Ansatz mit ORDER_BY und LIMIT für die innere Aussage
andig
Beachten Sie, dass dies kein Ergebnis zurückgibt, wenn vor dem angeforderten keine Datensätze vorhanden sind.
Andig
61
SELECT MAX(col) FROM table WHERE col NOT IN (SELECT MAX(col) FROM table);
Vinoy
quelle
31

In T-Sql gibt es zwei Möglichkeiten:

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

In Microsoft SQL ist der erste Weg doppelt so schnell wie der zweite, selbst wenn die betreffende Spalte gruppiert ist.

Dies liegt daran, dass der Sortiervorgang im Vergleich zu dem von der maxAggregation verwendeten Tabellen- oder Index-Scan relativ langsam ist .

Alternativ können Sie in Microsoft SQL 2005 und höher die folgende ROW_NUMBER()Funktion verwenden:

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

Ich sehe hier sowohl einige SQL Server-spezifische als auch einige MySQL-spezifische Lösungen, daher möchten Sie möglicherweise klären, welche Datenbank Sie benötigen. Wenn ich raten müsste, würde ich SQL Server sagen, da dies in MySQL trivial ist.

Ich sehe auch einige Lösungen, die nicht funktionieren, weil sie die Möglichkeit von Duplikaten nicht berücksichtigen. Seien Sie also vorsichtig, welche Sie akzeptieren. Schließlich sehe ich einige, die funktionieren werden, aber zwei vollständige Scans der Tabelle durchführen. Sie möchten sicherstellen, dass beim 2. Scan nur 2 Werte angezeigt werden.

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

Aktualisieren:

SQL Server 2012 unterstützt jetzt eine viel sauberere (und standardmäßige ) OFFSET / FETCH-Syntax:

SELECT TOP 2 [column] 
FROM [Table] 
GROUP BY [column] 
ORDER BY [column] DESC
OFFSET 1 ROWS
FETCH NEXT 1 ROWS ONLY;
Joel Coehoorn
quelle
Das hatte ich mir erhofft zu sehen. Die akzeptierte Antwort wird hässlich, wenn Sie sie benötigen, um für eine zu arbeiten n. Dieser besteht diesen Test.
Robin Maben
@RobinMaben Robin, wie wäre es mit dem Szenario, in dem der größte Wert wiederholt wird? Angenommen, eine Spalte enthält die Nummern 1 bis 100, aber 100 wird zweimal wiederholt. Dann erzeugt diese Lösung den zweitgrößten Wert als 100, was falsch ist. Richtig?
Pankaj Sharma
1
@PankajSharma Nein, dies wird aufgrund der GROUP BY-Klausel
Joel Coehoorn
Dies ist die Standardmethode. Die akzeptierte Antwort sollte auf diese aktualisiert werden.
Guilherme Melo
1
Ich erhalte eine Fehlermeldung, dass ich nicht TOPund OFFSETin derselben Abfrage verwenden kann.
Falsche
15

Ich nehme an, Sie können so etwas tun:

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

oder

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

abhängig von Ihrem Datenbankserver. Hinweis: SQL Server führt kein LIMIT aus.

Dguaraglia
quelle
Update-SQL Server 2012 fügte eine Offset / Fetch-Klausel ähnlich der oben genannten dbadiaries.com/…
iliketocode
Angenommen, Sie haben 2 Elemente mit demselben Wert, aber auch das größte Element. Ich denke, Sie müssen tunOFFSET 2
Kangkan
Durch Hinzufügen der GROUP BY-Klausel wird die doppelte Bedingung in diesem Fall berücksichtigt.
Saif
7

Am einfachsten wäre es, den zweiten Wert aus dieser Ergebnismenge in der Anwendung zu erhalten:

SELECT DISTINCT value FROM Table ORDER BY value DESC LIMIT 2

Wenn Sie jedoch den zweiten Wert mithilfe von SQL auswählen müssen, wie wäre es mit:

SELECT MIN(value) FROM (SELECT DISTINCT value FROM Table ORDER BY value DESC LIMIT 2) AS t
Magnar
quelle
1
Haben Sie dies auf SQL Server ausgeführt?
Craig
1
@Craig - LIMITist MySQL-Syntax, die Frage gibt keine SQL-Version an.
Keith
4

Eine sehr einfache Abfrage, um den zweitgrößten Wert zu finden

SELECT `Column` FROM `Table` ORDER BY `Column` DESC LIMIT 1,1;
Petcy
quelle
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

Keine Unterabfragen erforderlich ... überspringen Sie einfach eine Zeile und wählen Sie die zweite Zeile nach der Reihenfolge absteigend aus

Justin Jose
quelle
3
SELECT MAX(Salary) FROM Employee WHERE Salary NOT IN (SELECT MAX(Salary) FROM Employee )

Diese Abfrage gibt das maximale Gehalt aus dem Ergebnis zurück, das kein maximales Gehalt aus der Gesamttabelle enthält.

Naresh Kumar
quelle
2
Können Sie bearbeiten , um zu erklären, wie sich dies erheblich von den alten Antworten unterscheidet?
Nathan Tuggy
3

Alte Frage, die ich kenne, aber das gab mir einen besseren Ausführungsplan:

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

Dies ist ein sehr einfacher Code. Sie können Folgendes ausprobieren: -

Beispiel: Tabellenname = Test

salary 

1000
1500
1450
7500

MSSQL-Code, um den zweitgrößten Wert zu erhalten

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

Hier bedeutet "Versatz 1 Zeilen" die 2. Tabellenzeile und "Nur die nächsten 1 Zeilen abrufen", um nur diese 1 Zeile anzuzeigen. Wenn Sie nicht "Nur die nächsten 1 Zeilen abrufen" verwenden, werden alle Zeilen aus der zweiten Zeile angezeigt.

Nijish.
quelle
Optimierteste und ressourcenschonendste Antwort. Ich habe ziemlich viel Zeit gespart, indem ich es in meiner Unterabfrage verwendet habe. Vielen Dank.
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

Hoffe diese Hilfe, um den Wert für jede Zeile zu erhalten .....

Rohit Singh
quelle
2

Am einfachsten von allen

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

Hinweis

sal ist col name
emp ist tabellenname

Ni3
quelle
1

Tom, glaube, dies wird fehlschlagen, wenn mehr als ein Wert im select max([COLUMN_NAME]) from [TABLE_NAME]Abschnitt zurückgegeben wird. dh wenn der Datensatz mehr als 2 Werte enthält.

Eine geringfügige Änderung Ihrer Abfrage funktioniert -

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

Die Unterabfrage gibt alle anderen Werte als den größten zurück. Wählen Sie den Maximalwert aus der zurückgegebenen Liste.

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

Es ist der esiest Weg:

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

Wie Sie bereits erwähnt haben, doppelte Werte. In diesem Fall können Sie DISTINCT und GROUP BY verwenden , um den zweithöchsten Wert zu ermitteln

Hier ist eine Tabelle

Gehalt

::

Geben Sie hier die Bildbeschreibung ein

GRUPPIERE NACH

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

UNTERSCHEIDLICH

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

Erster Teil von LIMIT = Startindex

Zweiter Teil von LIMIT = wie viele Werte

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

Dies gibt den dritthöchsten Wert von emp table zurück

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

nicht in ist eine Bedingung, die den höchsten Wert von column_name ausschließt.

Referenz: Programmiererinterview

Hautausschläge
quelle
0

Etwas wie das? Ich habe es jedoch nicht getestet:

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

Verwenden einer korrelierten Abfrage:

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

Diese Abfrage wählt die maximal drei Gehälter aus. Wenn zwei Mitarbeiter das gleiche Gehalt erhalten, hat dies keine Auswirkungen auf die Abfrage.

etw
quelle
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
quelle
0

Dies funktioniert in MS SQL:

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