2017-01-09 3 views
19

Ich führe die folgende Abfrage aus, um das dritthöchste Gehalt von der Angestelltentabelle zu bekommen, und es hat richtig funktioniert, aber ich kann seine Logik nicht verstehen. Wie stimmen die Werte der Unterabfrage mit der Hauptabfrage überein (linker Teil) Kann jemand bitte erklären, welche Logik hinter dieser Abfrage steckt?Wie arbeitet die Logik hinter dieser Abfrage?

select e1.salary 
from employee as e1 
where 3 = (select count(salary) 
      from employee as e2 
      where e1.salary<=e2.salary) 

PS: Ich kann die count() kehrt Anzahl der Zeilen verstehen (wo alle Datensätze eindeutig sind).

+6

Für jemanden auf einer sehr grundlegenden Ebene des Verständnisses; Warum ist das so kompliziert? Kannst du dies nicht mit RANK oder ROW_NUMBER in Kombination mit ORDER BY erreichen? Gibt es einen Erbenwert, wenn man es wie ein OP-Beispiel macht? –

+2

@StianYttervik Ich würde raten, wer auch immer es geschrieben hat, weiß nicht RANK oder ROW_NUMBER existieren – Caleth

+2

Okay, nahe Wähler. Der Teufel stimmt nicht mit euch allen? Das ist * Nirgendwo * eine Empfehlungsfrage. (Im Ernst, wo hast du das überhaupt hinbekommen?) Und die Frage ist klar genug, wie einige nette Antworten zeigen, die erklären, was die Abfrage tut. Ich würde sogar argumentieren, dass diese Frage nicht "grundlegend" ist; Es ist nicht unvernünftig, von dieser Abfrage verwirrt zu sein, wenn Sie noch SQL-Grundlagen verstehen. (Verdammt, selbst wenn du dich in SQL auskennst, könnte es eine Minute dauern, es zu starren, um es herauszufinden.) Wenn du für das Schließen stimmst, * finde zuerst einen guten Grund *. – jpmc26

Antwort

5

Jedes Gehalt in employee Tabelle e1 wird an die sub-query weitergegeben. Sub-query finden Sie alle salaries diejenigen sind weniger als die salary bestanden und zählen Sie.

Für eine bestandene Gehalt, wenn die Unterabfrage gibt als 3 zählen dann das Gehalt wird in Folge

betrachten gibt es 5 Datensätze in Tabelle employee

1 
2 
3 
4 
5 
6 
7 
8 

wenn 1 von e1 geben wird ist die Unterabfrage wie folgt:

nun die Zählung innerhalb Teilabfrage wird 8 sein, weil alle Datensätze größer sind als oder gleich 1 Count nicht gleich 3, so wird nicht salary 1


zurückgegeben werden, wenn 2 von e1 übergeben wird, die Unter Abfrage wird wie sein

select e1.salary 
from employee as e1 
where 3 = (select count(salary) 
      from employee as e2 
      where 2<=e2.salary) 

nun die Zählung innerhalb Sub-Abfrage 7 sein wird, weil außer 1 alle Datensätze größer als oder gleich 2 Count nicht gleich zu 3 so Salary 2 es nicht sein wird, zurückgegeben


wenn 6 von e1 übergeben wird, wird die Unterabfrage sein wie

select e1.salary 
from employee as e1 
where 3 = (select count(salary) 
      from employee as e2 
      where 6<=e2.salary) 

nun drei Datensätze größer als oder gleich 6 (IE) sind 6,7,8, so wird der Zählwert 3 ist und Bedingung ist erfüllt. So wird salary 6 zurückgegeben

+0

oder du meinst 6 <= 6 –

+0

@JasonClark - Entschuldigung Ich habe das nicht .. –

+0

Ich möchte Unterabfrage-Prozess nach Where-Klausel, nehme an, wenn ich 4 Datensätze wie 25000, 15000, 10000, 17000. Dann wie Unterabfrage auf diese Werte ausführen, wenn ich 3. höchste Gehalt erhalten möchte? –

1

In der Tat ist es ziemlich einfach. Die zweite Abfrage wählt alle Mitarbeiter aus, für die der aktuelle (ausgewählte) Mitarbeiter (e1) ein niedrigeres Gehalt hat. Wir sagen dann, dass die Anzahl der Angestellten mit einem niedrigeren oder gleichen Gehalt 3 sein muss. Was dazu führt, dass das dritthöchste Gehalt erreicht wird.

21

Diese Abfrage wird im Grunde sagen:

for each row in employee assign to e1 
    count = 0 
    for each row in employee assign to e2 
     if e1.salary <= e2.salary 
      count = count + 1 
     end if 
    end for 
    if count = 3 
     add e1 to result set 
    end if 
end for 
return result set 

Zusammengefasst für jede Zeile in der Tabelle employee es die Tabelle ein zweites Mal besucht und die Anzahl der Zeilen mit einem niedrigeren oder gleich Gehalt zu zählen. Wenn es genau 3 gibt, wird die Zeile zum Ergebnis hinzugefügt.

Es ist erwähnenswert, dass dies schief gehen kann, wenn es mehr als einen Angestellten mit dem gleichen Gehalt gibt. Was Sie wahrscheinlich wollen, ist eine Abfrage mit einer Ranking-Funktion. So etwas wie dieses:

SELECT salary 
FROM 
    (SELECT 
     salary 
     ,DENSE_RANK() OVER (ORDER BY salary DESC) [rank] 
    FROM employee) t 
WHERE 
    [rank] = 3 

Was genau ist mit "3rd Highest" gemeint ist vielleicht ein bisschen mehrdeutig. Wenn wir die Gehälter haben 8, 8, 6, 5 die oben wird 5. zurückkehren, wenn wir 6 wollen Sie müssen die DENSE_RANK ändern, wie dies ROW_NUMBER:

SELECT salary 
FROM 
    (SELECT 
     salary 
     ,ROW_NUMBER() OVER (ORDER BY salary DESC) [rank] 
    FROM employee) t 
WHERE 
    [rank] = 3 

Die DENSE_RANK Version oben auch von der Rückkehr mehr Zeilen leiden wenn es eine Krawatte für den dritten Platz gibt. Ob dies wünschenswert ist oder nicht, hängt davon ab, was genau benötigt wird, aber es ist möglich, dies durch eine Aggregatfunktion auf das Gehalt zu reduzieren.

SELECT MAX(salary) 
FROM 
    (SELECT 
     salary 
     ,DENSE_RANK() OVER (ORDER BY salary desc) [rank] 
    FROM employee) t 
WHERE 
    [rank] = 3 
6

Betrachten wir diese Werte:

Salary: 
1 
2 
3 
4 
5 
6 
7 
8 

e1 e2 
1 1 
2 2 
3 3 
4 4 
5 5 
6 6 
7 7 
8 8 

Für e1.1 gibt es 8 Reihen in e2, die größer oder gleich e1.1 sind.

Für e1.2 gibt es 7 Zeilen in e2, die größer oder gleich e1.2 sind.

...

Für e1.6 es 3 Reihen in e2 sind, die e1.6 größer oder gleich sind.

Dies ist eine seltsame und verwirrende Select-Anweisung. Ich würde nur umschreiben es mit DENSE_RANK Fensterfunktion, denn wenn Sie mehrere Zeilen mit demselben Gehalt haben, werden Sie nicht korrekte Ergebnisse erhalten:

DECLARE @t TABLE (i INT) 
INSERT INTO @t 
VALUES (1), 
     (2), 
     (3), 
     (4), 
     (5), 
     (6), 
     (8), 
     (8); 


WITH cte 
      AS (SELECT * , 
         DENSE_RANK() OVER (ORDER BY i DESC) AS rn 
       FROM  @t 
      ) 
    SELECT * 
    FROM cte 
    WHERE rn = 3 

Ergebnisse in 5 während Ihrer erste select-Anweisung in 6 führen wird, dass ich glaube, ist nicht dritthöchstes Gehalt überhaupt.

+2

Für die meisten Menschen bedeutet "das dritthöchste Gehalt" das Gehalt der dritthöchsten Angestellten, also wäre das erwartete Ergebnis von 5, 6, 8, 8 6. –

Verwandte Themen