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.
Diese Antwort funktioniert, vielen Dank – Joesph
@Joesph - Eigentlich ist diese Antwort ** falsch **. Denken Sie darüber nach, was passiert, wenn Sie zwei Mitarbeiter mit demselben Nachnamen haben. – mathguy