2016-10-15 7 views
0

mit GROUP Es gibt zwei Tabellen:Oracle SQL-Abfrage - immer SUM() aus einer anderen Tabelle BY

Employee-Tabelle:

employee_id, lname 
E01  | Smith 
E02  | Johnson 
E03  | Williams 
E04  | Jones 

Gehaltstabelle:

employee_id, paid 
E01  | 199 
E04  | 751 
E01  | 599 
E02  | 299 
E03  | 259 
E03  | 357 
E02  | 671 
E04  | 130 

Wie frage ich nur die Nachnamen des Mitarbeiters und ihre Gesamt Gehalt verdient? Mein Versuch, zog zu viele Zeilen:

SELECT lname, total_paid 
FROM Employee 
CROSS JOIN (SELECT SUM(paid) AS total_paid FROM Salary GROUP BY employee_id); 

Mein Problem ist, ich brauche die Summe aus dem bezahlten Tisch verdient select, was bedeutet, ich brauche SUM und GROUP BY zu verwenden, wenn ich mich nicht irre. Allerdings möchte ich nur lname und die gesamte ...

Antwort

0

Sie müssen die Tabellen verknüpfen und dann aggregieren:

SELECT e.lname, SUM(s.paid) as total_paid 
FROM Employee e JOIN 
    Salary s 
    ON e.employee_id = s.employee_id 
GROUP BY e.lname; 

Hinweis:

  • Verwenden Sie ein LEFT JOIN wenn einige Mitarbeiter keine Gehälter haben.
  • Dies ist die Standardmethode, um das zu tun, was Sie wollen. Sie könnten auch eine korrelierte Unterabfrage verwenden.
  • Die nicht aggregierte Spalte in der SELECT (lname) sollte die in der GROUP BY sein.
  • Alle Spalten sind qualifizierte, was bedeutet, dass sie Tabellen Aliase haben.
+0

Diese Antwort funktioniert, vielen Dank – Joesph

+0

@Joesph - Eigentlich ist diese Antwort ** falsch **. Denken Sie darüber nach, was passiert, wenn Sie zwei Mitarbeiter mit demselben Nachnamen haben. – mathguy

0

auswählen Sie können diese query stattdessen Ihre verwenden. Machen Sie den linken Join in der Salary-Tabelle in employee_id-Spalten.

SELECT Employee.lname, SUM(Salary.paid) as total_paid FROM Employee 
LEFT JOIN Salary on Employee.employee_id=Salary.employee_id 
GROUP BY Employee.employee_id 
+0

Oracle SQL-Entwickler gab mir einen Fehler auf der letzten GROUP BY-Zeile - "Spalte zweideutig definiert". Wenn ich employee.employee_id oder salary.employee_id verwendet habe, heißt das, dass es "kein GROUP BY-Ausdruck" ist. – Joesph

+0

Alias ​​it wie Salary.paid, Employee.lname, Employee.employee_id usw. Aber bessere Idee ist die Verwendung von GROUP BY Employee.lname. –

+0

Danke, ich habe es jetzt :) – Joesph

0

Eine Alternative zu den Lösungen von Gordon und mww besteht darin, zuerst zu aggregieren und dann die Verbindung herzustellen. (Es ist möglich, dass der Oracle-Optimierer sowieso eine der Lösungen in die andere transformiert, bevor die Abfrage ausgeführt wird - ich finde das eine interessante Frage, ich werde experimentieren und zurückmelden). Das ist auch sehr nah an dem, was Sie versucht haben - CROSS Join war der Fehler. Sie müssen die employee_id in der Unterabfrage behalten und auf employee_id beitreten.

Bearbeiten: Eigentlich ist die Antwort von Gordon und mww inkorrekt. Beide Antworten gruppieren sich nach dem Nachnamen des Mitarbeiters, wobei die Tatsache ignoriert wird, dass es verschiedene Mitarbeiter mit demselben Nachnamen geben kann. Also mein "Testen, um zu sehen, was der Oracle Optimizer tut" ist strittig; Die Abfragen sind NICHT gleichwertig.

Ein weiterer Punkt ist, dass der linke Join die total_paid als NULL für einen Mitarbeiter belässt, der keine entsprechenden Zeilen in der Saladetabelle hat. Wenn Sie stattdessen 0 (Null) benötigen, können Sie einen CASE Ausdruck oder ein Äquivalent in diesem Fall NVL() verwenden.

select e.lname, nvl(g.total_paid, 0) as total_paid 
from employee e left join (select employee_id, sum(paid) as total_paid  
           from  salary 
           group by employee_id 
          ) g 
        on e.employee_id = g.employee_id; 

Testergebnisse

ich meine Lösung zu Gordon und mww der Vergleich (vorausgesetzt, sie beide lname UND employee_id in GROUP BY enthalten sind korrigiert, die andere Art und Weise ihre Lösungen zu beheben ist MAX(lname) as lname und GROUP BY employee_id wählen allein). Ich habe dies anhand des SCOTT-Schemas getan, indem ich die EMP- und DEPT-Tabellen verwendet habe, um die Gehälter nach Abteilung zusammenzufassen. ziemlich genau das gleiche Problem.

Der Optimierer wandelt die eine Lösung NICHT in die andere um - ein Plan gruppiert zuerst und tritt dann ein, während der andere zuerst eintritt und dann gruppiert. Die Kosten des Optimierers waren gleich (für die sehr kleinen Eingabetabellen), aber die Kardinalität war größer, wenn man zuerst antritt.

Dies ist zu erwarten: Angenommen EMP hat 1000 Reihen, aber es gibt nur 4 Abteilungen. Wenn eine Gruppe zuerst gruppiert wird, wird die EMP-Tabelle auf 4 Zeilen aggregiert, die mit DEPT verbunden sind. Auf der anderen Seite, wenn wir zuerst beitreten, verbinden wir 1000 Reihen mit 4 Reihen - und dann sammeln wir immer noch 1000 resultierende Reihen auf 4, genau wie in der anderen Lösung. Der einzige Unterschied ist die Kardinalität des Joins.

JEDOCH: Ich wiederholte den gleichen Test auf das HR-Schema. In diesem Fall hat der Optimierer eine Lösung in die andere transformiert - zuerst den Join und erst dann die Gruppierung. Der Unterschied besteht in diesem Fall darin, dass es in beiden Tabellen Indizes für die Abteilung_ID gibt, und der Optimierer kann davon profitieren (und die Verknüpfung VIEL schneller ausführen), aber nur, wenn er zuerst eintritt. Wenn es zuerst gruppiert wird, gibt es keinen "Index" für die resultierende Spalte department_id.

Also: "es kommt darauf an" (wie bei so vielen anderen Dingen). In jedem Fall, wenn es einen Index gibt und der Optimierer denkt, dass es am besten ist, den Join zuerst zu machen, wird es dies tun. Anscheinend nicht umgekehrt.

Verwandte Themen