27th Jul 2023 15 Leseminuten Wie man SUM() mit OVER(PARTITION BY) in SQL verwendet Martyna Sławińska Window Functions Inhaltsverzeichnis Die OVER()-Klausel in SQL Beispiel 1A: Berechnen der Summe für jede Gruppe - SUM() mit OVER(PARTITION BY ...) Beispiel 1B: Berechnung des Gehalts für jede Stellenbezeichnung Beispiel 2: Berechnen des Verhältnisses zwischen dem Wert einer einzelnen Zeile und der Gesamtsumme Beispiel 2: Berechnen des Verhältnisses zwischen dem Wert einer einzelnen Zeile und der Gesamtsumme Was ist der Unterschied zwischen SUM() mit OVER(PARTITION BY …) und der Verwendung von SUM() mit GROUP BY? Beispiel 3: Berechnen einer laufenden Summe mit SUM() mit OVER(PARTITION BY) Beispiel 4: Zählen von Objekten in benutzerdefinierten Kategorien Beispiel 5: Berechnen einer Auftragssumme mit Rabatten unter Verwendung von SUM() mit CASE WHEN Weiter und SUM() mit OVER() und PARTITION BY Entdecken Sie reale Anwendungsfälle der Funktion SUMME() mit der Klausel OVER(PARTITION BY). Lernen Sie die Syntax und sehen Sie sich 5 verschiedene Beispiele an. Wir verwenden SQL-Fensterfunktionen, um Operationen mit Datengruppen durchzuführen. Zu diesen Operationen gehören die mathematischen Funktionen SUM(), COUNT(), AVG(), und weitere. In diesem Artikel wird erklärt, was SUM() mit OVER(PARTITION BY) in SQL macht. Wir zeigen Ihnen die häufigsten Anwendungsfälle in realen Anwendungen, um das Verhältnis zwischen dem Wert einer einzelnen Zeile und dem Gesamtwert zu bestimmen, laufende Summen zu berechnen und eine benutzerdefinierte Bestellsumme zu finden, die Rabatte für bestimmte Produkte enthält. Um eine ausführliche Anleitung zur Verwendung von SUM() mit OVER() und anderen Fensterfunktionen zu erhalten, besuchen Sie unseren interaktiven Fensterfunktionen Kurs. Er erklärt alle SQL-Fensterfunktionskonzepte im Detail und enthält über 200 Übungen. Fangen wir an. Die OVER()-Klausel in SQL In SQL wird die OVER() Klausel verwendet, um Fensterfunktionen einzuführen. Die allgemeine Syntax lautet: SELECT … <window function> OVER(...) … OVER() teilt der Datenbank mit, dass wir Fensterfunktionen verwenden wollen. Die Fensterfunktion kann eine Aggregatfunktion sein, wie SUM(), oder eine andere Fensterfunktion. Eine Fensterfunktion arbeitet mit einem "Fensterrahmen" oder einer Reihe von Zeilen, die mit der aktuellen Zeile in Beziehung stehen. OVER() definiert den Fensterrahmen für jede Zeile. Eine leere OVER() Klausel teilt der Datenbank mit, dass die gesamte Ergebnismenge der Fensterrahmen ist. Sehen wir uns ein Beispiel für die SUM() OVER() -Syntax an. Wir verwenden die employees Tabelle aus den Beispieldaten, die von Oracle Live SQL bereitgestellt werden. Diese Tabelle besteht aus den folgenden Spalten: emp_id ist die Kennung des Mitarbeiters. name ist der Name des Mitarbeiters. job ist die Stellenbezeichnung. dept_id Kennung der Abteilung. salary ist das Gehalt des Mitarbeiters. EMP_IDNAMEJOBDEPT_IDSALARY 7839KINGPRESIDENT105000 7698BLAKEMANAGER302850 … 7900JAMESCLERK30950 7934MILLERCLERK101300 Wir können die Funktion SUM() mit der Klausel OVER() verwenden, um das Gesamtgehalt aller Mitarbeiter zu erhalten und das Gesamtgehalt neben dem Gehalt jedes Mitarbeiters anzuzeigen. SELECT emp_id, name, job, dept_id, salary, SUM(salary) OVER() AS total_salary FROM employees; emp_idNAMEJOBDEPT_IDSALARYTOTAL_SALARY 7839KINGPRESIDENT10500029025 7698BLAKEMANAGER30285029025 … 7900JAMESCLERK3095029025 7934MILLERCLERK10130029025 Die Funktion SUM() wird für jede Zeile der Tabelle ausgeführt. Jedes Mal, wenn sie aufgerufen wird, holt sie die Gehaltsinformationen aus allen Zeilen der Tabelle, um den Gesamtbetrag des Gehalts zu berechnen. Das Gesamtgehalt wird neben den Angaben zu jeder einzelnen Zeile angezeigt. Die Details der einzelnen Zeilen werden beibehalten und neben dem Gesamtgehalt angezeigt. In diesem Beispiel ist der Fensterrahmen (die Menge der Zeilen, mit denen SUM() arbeitet) der gesamte Datensatz. Sie können zusätzliche Klauseln in OVER() hinzufügen, um den Fensterrahmen zu ändern. Beispiel 1A: Berechnen der Summe für jede Gruppe - SUM() mit OVER(PARTITION BY ...) Die Klausel OVER() kann Details über die Art und Weise enthalten, wie die Daten partitioniert werden sollen. Wir verwenden die PARTITION BY Klausel in OVER(), um die Daten in Partitionen oder Gruppen aufzuteilen. Die Verwendung von PARTITION BY ähnelt der Verwendung von GROUP BY, da die Zeilen auf der Grundlage der Werte einiger Spalten in Gruppen aufgeteilt werden. Bei Verwendung von SUM() OVER(PARTITION BY …) können wir die Summe der Werte für jede Gruppe oder Partition der Daten berechnen. Zum Beispiel können wir das Gesamtgehalt für jede Abteilung berechnen: SELECT emp_id, name, job, dept_id, salary, SUM(salary) OVER(PARTITION BY dept_id) AS dept_total_salary FROM employees; Hier ist das Ergebnis: EMP_IDNAMEJOBDEPT_IDSALARYDEPT_TOTAL_SALARY 7782CLARKMANAGER1024508750 7934MILLERCLERK1013008750 7839KINGPRESIDENT1050008750 7902FORDANALYST20300010875 7788SCOTTANALYST20300010875 7566JONESMANAGER20297510875 7369SMITHCLERK2080010875 7876ADAMSCLERK20110010875 7521WARDSALESMAN3012509400 7654MARTINSALESMAN3012509400 7844TURNERSALESMAN3015009400 7900JAMESCLERK309509400 7499ALLENSALESMAN3016009400 7698BLAKEMANAGER3028509400 Wir verwenden SUM(salary) OVER(PARTITION BY dept_id), um das Gesamtgehalt pro Abteilung zu ermitteln. Die Klausel PARTITION BY teilt die Zeilen in Gruppen auf der Grundlage der Spalte dept_id. Zeilen mit dept_id gleich 10 kommen in eine Gruppe (in der obigen Tabelle gelb markiert), die Zeilen mit dept_id gleich 20 kommen in eine andere Gruppe (grün markiert) und schließlich die Zeilen mit dept_id gleich 30 in eine weitere Gruppe (rot markiert). Die Funktion SUM() berechnet die Summe der Zeilen in jeder Gruppe. Beachten Sie, dass Sie bei der Verwendung von SUM() OVER(PARTITION BY) die Details der einzelnen Zeilen behalten. Sie können zum Beispiel die Details des Angestellten namens Ford sehen: seine Position, sein Gehalt und wie es im Vergleich zu den Gesamtgehältern in seiner Abteilung steht. Dies ist die typischste Verwendung von SUM() OVER(PARTITION BY): Sie berechnen den Summenwert für jede Datengruppe und behalten die Details der einzelnen Zeilen. Schauen wir uns ein ähnliches Beispiel an. Beispiel 1B: Berechnung des Gehalts für jede Stellenbezeichnung Wir können SUM(Gehalt) OVER(PARTITION BY job) verwenden, um das Gesamtgehalt pro Stellenbezeichnung zu ermitteln. Schauen wir es uns an: SELECT emp_id, name, job, dept_id, salary, SUM(salary) OVER(PARTITION BY job) AS job_total_salary FROM employees; Hier ist das Ergebnis: EMP_IDNAMEJOBDEPT_IDSALARYJOB_TOTAL_SALARY 7782CLARKMANAGER1024508275 7698BLAKEMANAGER3028508275 7566JONESMANAGER2029758275 7934MILLERCLERK1013004150 7369SMITHCLERK208004150 7876ADAMSCLERK2011004150 7900JAMESCLERK309504150 7902FORDANALYST2030006000 7788SCOTTANALYST2030006000 7521WARDSALESMAN3012505600 7654MARTINSALESMAN3012505600 7844TURNERSALESMAN3015005600 7499ALLENSALESMAN3016005600 7839KINGPRESIDENT1050005000 Diesmal werden die Zeilen nach dem Wert der Stelle und nicht nach der Abteilungs-ID gruppiert. Mitarbeiter mit der gleichen Position werden in einer Gruppe zusammengefasst, und wir berechnen das Gesamtgehalt der Mitarbeiter in dieser Position. Die Funktion SUM() wird auf alle Gehälter in jeder Gruppe angewandt: Das Gesamtgehalt für die Gruppe "Manager" ist die Summe aus 2450, 2850 und 2975, also den Gehältern der drei Manager in unserer Tabelle. Beispiel 2: Berechnen des Verhältnisses zwischen dem Wert einer einzelnen Zeile und der Gesamtsumme Normalerweise wollen wir den Vergleich zwischen jeder einzelnen Zeile und der Gesamtsumme sehen. Berechnen wir also den prozentualen Anteil jedes einzelnen Gehalts an der Gesamtsumme der Gehälter in der jeweiligen Abteilung. SELECT emp_id, name, job, dept_id, salary, ROUND(100.0 * salary / SUM(salary) OVER(PARTITION BY dept_id), 2) AS percentage_of_dept_total_salary FROM employees; EMP_IDNAMEJOBDEPT_IDSALARYPERCENTAGE_OF_DEPT_TOTAL_SALARY 7782CLARKMANAGER10245028 7934MILLERCLERK10130014.86 7839KINGPRESIDENT10500057.14 7902FORDANALYST20300027.59 7788SCOTTANALYST20300027.59 7566JONESMANAGER20297527.36 7369SMITHCLERK208007.36 7876ADAMSCLERK20110010.11 7521WARDSALESMAN30125013.3 7654MARTINSALESMAN30125013.3 7844TURNERSALESMAN30150015.96 7900JAMESCLERK3095010.11 7499ALLENSALESMAN30160017.02 7698BLAKEMANAGER30285030.32 Diesmal werden die Zeilen nach dem Wert job und nicht nach der Abteilungs-ID gruppiert. Mitarbeiter mit der gleichen Position werden in einer Gruppe zusammengefasst, und wir berechnen das Gesamtgehalt der Mitarbeiter in dieser Position. Die Funktion SUM() wird auf alle Gehälter in jeder Gruppe angewandt: Das Gesamtgehalt für die Gruppe "Manager" ist die Summe von 2450, 2850 und 2975, die die Gehälter der drei Manager in unserer Tabelle sind. Beispiel 2: Berechnen des Verhältnisses zwischen dem Wert einer einzelnen Zeile und der Gesamtsumme Normalerweise wollen wir den Vergleich zwischen jeder einzelnen Zeile und der Gesamtsumme sehen. Berechnen wir den prozentualen Anteil jedes einzelnen Gehalts an den Gesamtgehältern in der jeweiligen Abteilung. SELECT emp_id, name, job, dept_id, salary, ROUND(100.0 * salary / SUM(salary) OVER(PARTITION BY dept_id), 2) AS percentage_of_dept_total_salary FROM employees; EMP_IDNAMEJOBDEPT_IDSALARYPERCENTAGE_OF_DEPT_TOTAL_SALARY 7782CLARKMANAGER10245028 7934MILLERCLERK10130014.86 7839KINGPRESIDENT10500057.14 7902FORDANALYST20300027.59 7788SCOTTANALYST20300027.59 7566JONESMANAGER20297527.36 7369SMITHCLERK208007.36 7876ADAMSCLERK20110010.11 7521WARDSALESMAN30125013.3 7654MARTINSALESMAN30125013.3 7844TURNERSALESMAN30150015.96 7900JAMESCLERK3095010.11 7499ALLENSALESMAN30160017.02 7698BLAKEMANAGER30285030.32 Wir können zum Beispiel sehen, dass der Analyst Scott ein individuelles Gehalt von 3000 hat; das sind 27,59 % der Gesamtgehälter in seiner Abteilung. Nachfolgend eine Aufschlüsselung der Funktionen, die zur Erfüllung dieser Aufgabe verwendet werden: Wir nehmen jedes einzelne Gehalt und teilen es durch das Gesamtgehalt der Abteilung: salary / SUM(salary) OVER(PARTITION BY dept_id) Um einen Prozentsatz zu erhalten, multiplizieren wir ihn mit 100%: 0 * salary / SUM(salary) OVER(PARTITION BY dept_id) Anschließend verwenden wir die Funktion ROUND(), um zwei Dezimalstellen zu erhalten: ROUND(100.0 * salary / SUM(salary) OVER(PARTITION BY dept_id), 2) Die Berechnung des Verhältnisses zwischen der einzelnen Zeile und der Summe für eine Gruppe ist ein weiterer häufiger Anwendungsfall von SUMME() mit OVER(PARTITION BY). Auf ähnliche Weise können Sie die Differenz zwischen der Gesamtsumme für die Gruppe und der einzelnen Zeile berechnen. Was ist der Unterschied zwischen SUM() mit OVER(PARTITION BY …) und der Verwendung von SUM() mit GROUP BY? Die Klausel PARTITION BY erfüllt eine ähnliche Aufgabe wie die Klausel GROUP BY. Sowohl OVER(PARTITION BY) als auch GROUP BY unterteilen den Datensatz in Partitionen oder Gruppen. Wenn Sie die Funktion SUM() verwenden, berechnen beide Ausdrücke die Summe für jede Gruppe. Welchen Ausdruck sollten Sie also wählen? Bei der Verwendung von GROUP BY werden die Details der einzelnen Zeilen eingeklappt. Schauen Sie sich das an: SELECT job, SUM(salary) AS total_salary FROM employees GROUP BY job; JOBTOTAL_SALARY ANALYST6000 CLERK4150 SALESMAN5600 MANAGER8275 PRESIDENT5000 Hier erhalten wir den Gesamtwert der Gehälter für jede Stellenbezeichnung, ohne die Gehälter der einzelnen Mitarbeiter zu berücksichtigen. Wenn Sie jedoch den Gesamtsummenwert mit den Werten der einzelnen Zeilen vergleichen möchten (z. B. um das Verhältnis zwischen dem Einzelwert und dem Gesamtwert zu berechnen), sollten Sie OVER(PARTITION BY …) verwenden. Hier werden alle einzelnen Zeilen zusammen mit dem Gesamtsummenwert für jede Zeile zurückgegeben. Dieser Gesamtsummenwert kann unterschiedlich sein, je nachdem, zu welcher Partition die Zeile gehört. SELECT name, job, salary, SUM(salary) OVER(PARTITION BY job) AS total_salary FROM employees; NAMEJOBSALARYTOTAL_SALARY FORDANALYST30006000 SCOTTANALYST30006000 SMITHCLERK8004150 JAMESCLERK9504150 ADAMSCLERK11004150 MILLERCLERK13004150 BLAKEMANAGER28508275 JONESMANAGER29758275 CLARKMANAGER24508275 KINGPRESIDENT50005000 TURNERSALESMAN15005600 ALLENSALESMAN16005600 WARDSALESMAN12505600 MARTINSALESMAN12505600 Der Wert total_salary entspricht den Ergebnissen der vorherigen Abfrage mit GROUP BY. Hier können Sie jedoch auch die einzelnen Gehälter sehen. Zum Beispiel gibt es zwei Analysten, die insgesamt 6000 verdienen; jeder von ihnen verdient 3000. Als Faustregel gilt: Wenn Sie nur den Summenwert für jede Gruppe wissen wollen und nicht an den Details für jede einzelne Zeile interessiert sind, sollten Sie die Klausel GROUP BY verwenden. Wenn Sie sowohl an der Summe für jede Gruppe als auch an den Details der einzelnen Zeilen interessiert sind, sollten Sie SUM() OVER(PARTITION BY) verwenden. Beispiel 3: Berechnen einer laufenden Summe mit SUM() mit OVER(PARTITION BY) Eine weitere häufige Verwendung der Syntax SUM() OVER(...) ist die Berechnung der laufenden Summe. Eine laufende Summe ist die kumulative Summe der vorherigen Zahlen in einer Spalte. Wir verwenden laufende Summen, um Werte zu berechnen, die sich im Laufe der Zeit ansammeln. Mit einer laufenden Summe können Sie beispielsweise die monatliche mobile Datennutzung berechnen, indem Sie den Wert jedes folgenden Tages zur Summe der Werte der vorherigen Tage addieren. In ähnlicher Weise können Sie berechnen, wie die Anzahl der registrierten Nutzer jeden Tag steigt oder wie der Gesamtumsatz mit jeder Transaktion zunimmt. Wir verwenden die Syntax SUM() mit OVER(PARTITION BY … ORDER BY …), um die laufende Summe zu berechnen. Schauen wir uns ein Beispiel an. Wir verwenden die orders Tabelle aus den Beispieldaten von Oracle Live SQL. Diese Tabelle speichert historische Auftragsdaten. Jeder Auftrag hat ein Datum (order_date), einen Vertriebsmitarbeiter (sales_rep_id) und einen Gesamtwert (order_total). Hier berechnen wir den laufenden Gesamtwert für jeden Vertriebsmitarbeiter: SELECT order_date, sales_rep_id, order_total, SUM(order_total) OVER(PARTITION BY sales_rep_id ORDER BY order_date) AS running_total FROM orders; ORDER_DATESALES_REP_IDORDER_TOTALRUNNING_TOTAL 29-MAR-07 02.22.40.536996 PM15310794.610794.6 16-AUG-07 03.34.12.234359 PM15378279.689074.2 04-OCT-07 09.53.34.362632 PM15312989203.2 21-NOV-07 10.22.33.263332 AM15313824103027.2 16-DEC-07 08.19.55.462332 PM15311188.5114215.7 27-JUL-06 12.22.59.662632 PM15452471.952471.9 27-JUL-06 01.34.16.562632 PM154364656117.9 29-JUN-07 09.53.41.984501 AM1544856165.9 01-JUL-07 04.49.13.615512 PM15422056385.9 02-JUL-07 03.34.44.665170 AM15460056985.9 01-SEP-07 09.53.26.934626 AM154545162436.9 02-OCT-07 05.49.34.678340 PM1546653.469090.3 10-NOV-07 03.49.25.526321 AM15450125119215.3 19-NOV-07 02.41.54.696211 PM15442283.2161498.5 17-DEC-07 05.03.52.562632 PM15410474.6171973.1 Dazu partitionieren wir unsere Tabelle nach Vertriebsmitarbeitern und ordnen dann jede Partition nach Datum: SUM(order_total) OVER(PARTITION BY sales_rep_id ORDER BY order_date) Das neue Syntaxelement ist hier ORDER BY. Es legt fest, wie die Zeilen in jedem Fensterrahmen sortiert werden. Die Funktion SUM() wird auf jede Zeile angewendet; sie addiert den aktuellen Wert order_total zum vorherigen Wert running_total; laufende Summen werden für jede Partition (hier für jede Vertreter-ID) separat berechnet. Schauen wir uns den Vertriebsmitarbeiter mit der ID 153 genauer an. Sein erster Auftrag war am29. März und hatte einen Gesamtwert von 10794,6. Zu diesem Zeitpunkt ist die laufende Summe gleich dem Auftragswert. Die zweite Bestellung erfolgte am16. August für 78279,6; jetzt ist die laufende Summe gleich der Summe der Werte der ersten und zweiten Bestellung (10794,6 + 78279,6 = 89074,2). Nach der dritten Bestellung ist die laufende Summe gleich der vorherigen laufenden Summe plus dem Wert der dritten Bestellung (89074,2 + 129 = 89203,2). Für den Vertriebsmitarbeiter mit der ID 154 ist der Vorgang ähnlich. Das Berechnen einer laufenden Summe ist ein gängiges Muster bei der Verwendung von SQL für die Datenanalyse. Wie man eine laufende Summe in SQL berechnet, können Sie an anderer Stelle in unserem Blog nachlesen. Beispiel 4: Zählen von Objekten in benutzerdefinierten Kategorien Die Funktion SUM() wird oft mit der Anweisung CASE WHEN kombiniert, um Objekte in benutzerdefinierten Kategorien zu zählen. Sie möchten z. B. das Gesamtgehalt der Mitarbeiter in Führungspositionen in einer Abteilung berechnen und es neben den Details der einzelnen Mitarbeiter anzeigen. Dies können Sie erreichen, indem Sie SUM() OVER(PARTITION BY) in Kombination mit CASE WHEN verwenden. Schauen wir uns zunächst die Anweisung CASE WHEN an. Sie ähnelt der Anweisung if, die in vielen Programmiersprachen verwendet wird. Wir verwenden sie, um den Wert eines Ausdrucks in verschiedenen Situationen oder Fällen zu definieren. Im folgenden Beispiel verwenden wir die Anweisung CASE WHEN, um jeden Mitarbeiter als Führungskraft (Manager und Präsidenten) oder als normalen Mitarbeiter (alle anderen Stellen) zu identifizieren. Schauen Sie sich das an: SELECT emp_id, name, job, dept_id, CASE WHEN job IN (‘PRESIDENT’, ‘MANAGER’) THEN ‘MANAGEMENT’ ELSE ‘REGULAR’ END AS emp_type salary FROM employees; Die Anweisung CASE wertet alle Bedingungen von WHEN aus. Wenn sie die passende Bedingung findet, gibt sie den Wert in der Verzweigung THEN zurück. Findet sie die passende Bedingung nicht, gibt sie den Wert zurück, der hinter ELSE angegeben ist. In unserem Beispiel werden Mitarbeiter in der Position des Präsidenten oder Managers als 'Management' bezeichnet. Allen anderen Stellen wird die Bezeichnung "Regular" zugewiesen. Hier ist das Ergebnis der Abfrage: EMP_IDNAMEJOBDEPT_IDEMP_TYPESALARY 7782CLARKMANAGER10MANAGEMENT2450 7934MILLERCLERK10REGULAR1300 7839KINGPRESIDENT10MANAGEMENT5000 7902FORDANALYST20REGULAR3000 7788SCOTTANALYST20REGULAR3000 7566JONESMANAGER20MANAGEMENT2975 7369SMITHCLERK20REGULAR800 7876ADAMSCLERK20REGULAR1100 7521WARDSALESMAN30REGULAR1250 7654MARTINSALESMAN30REGULAR1250 7844TURNERSALESMAN30REGULAR1500 7900JAMESCLERK30REGULAR950 7499ALLENSALESMAN30REGULAR1600 7698BLAKEMANAGER30MANAGEMENT2850 Weitere Informationen über CASE finden Sie in unserem Artikel Wie man CASE in SQL verwendet. Sie können auch die Anweisung CASE mit SUM() verwenden, um Werte in benutzerdefinierten Kategorien zu summieren. Hier ist die Abfrage: SELECT dept_id, SUM( CASE WHEN job IN (‘PRESIDENT’, ‘MANAGER’) THEN salary ELSE 0 END) AS dept_management_salary, SUM( CASE WHEN job IN (‘PRESIDENT’, ‘MANAGER’) THEN 0 ELSE salary END) AS dept_regular_salary FROM employees GROUP BY dept_id; DEPT_IDDEPT_MANAGEMENT_SALARYDEPT_REGULAR_SALARY 1074501300 2029757900 3028506550 Für Mitarbeiter in Führungspositionen gibt die erste Anweisung CASE den Wert der Spalte salary zurück. Die Funktion SUM() in Kombination mit GROUP BY summiert dann alle Gehälter für Angestellte in Führungspositionen mit der gleichen dept_id. Auf diese Weise wird das gesamte Managementgehalt pro Abteilung berechnet. Die zweite Anweisung CASE berechnet das gesamte Abteilungsgehalt für alle regulären Mitarbeiter. Sie können das Gesamtgehalt für Mitarbeiter in leitender Position in einer Abteilung berechnen und es neben den Mitarbeiterdetails mit SUM() und PARTITION BY anzeigen: SELECT emp_id, name, job, dept_id, CASE WHEN job IN (‘PRESIDENT’, ‘MANAGER’) THEN ‘MANAGEMENT’ ELSE ‘REGULAR’ END AS emp_type salary, SUM( CASE WHEN job IN (‘PRESIDENT’, ‘MANAGER’) THEN salary ELSE 0 END) OVER(PARTITION BY dept_id) AS dept_management_salary FROM employees; EMP_IDNAMEJOBDEPT_IDEMP_TYPESALARYDEPT_MANAGEMENT_SALARY 7782CLARKMANAGER10MANAGEMENT24507450 7934MILLERCLERK10REGULAR13007450 7839KINGPRESIDENT10MANAGEMENT50007450 7902FORDANALYST20REGULAR30002975 7788SCOTTANALYST20REGULAR30002975 7566JONESMANAGER20MANAGEMENT29752975 7369SMITHCLERK20REGULAR8002975 7876ADAMSCLERK20REGULAR11002975 7521WARDSALESMAN30REGULAR12502850 7654MARTINSALESMAN30REGULAR12502850 7844TURNERSALESMAN30REGULAR15002850 7900JAMESCLERK30REGULAR9502850 7499ALLENSALESMAN30REGULAR16002850 7698BLAKEMANAGER30MANAGEMENT28502850 Die Zeilen werden anhand der Spalte dept_id in Gruppen eingeteilt. Es gibt drei Gruppen, eine für jede Abteilung. Die Funktion SUM() wird auf den Ausdruck CASE WHEN angewendet. Anstatt das Gesamtgehalt in jeder Abteilung zu berechnen, berechnen wir das Gesamtgehalt für Angestellte in Führungspositionen in der Abteilung. Die Funktion CASE gibt 0 für normale Angestellte (die Summe wird nicht erhöht) und den Gehaltswert für leitende Angestellte zurück. Sie können dieses Muster in vielen verschiedenen Situationen verwenden. Im nächsten Abschnitt werden wir ein weiteres Beispiel für die Kombination von CASE WHEN mit SUM() und OVER(PARTITION BY) sehen. Beispiel 5: Berechnen einer Auftragssumme mit Rabatten unter Verwendung von SUM() mit CASE WHEN In diesem Beispiel wollen wir den Gesamtwert für jede Bestellung berechnen, einschließlich der Rabatte für einige Bestellpositionen. Wir verwenden die Syntax SUM() OVER(PARTITION BY …), um alle Positionswerte pro Bestellung zu summieren. Und um die Produktrabatte einzubeziehen, verwenden wir die Anweisung CASE WHEN. Wir verwenden die order_items Tabelle aus den Beispieldaten, die von Oracle Live SQL bereitgestellt werden. In dieser Tabelle werden alle Bestellpositionen (product_id) gespeichert, die zu jeder Bestellung (order_id) gehören. Sie enthält Informationen über den Stückpreis des Produkts (unit_price) und die Bestellmenge (quantity). Nun wollen wir die Bestellwerte berechnen: einen für jedes Produkt in der Bestellung und einen Gesamtwert für die Bestellung; der Gesamtwert der Bestellung sollte alle auf die Produkte angewandten Rabatte enthalten. Die Gesamtsumme der Bestellung ist gleich dem Stückpreis multipliziert mit der Bestellmenge. Wenn jedoch ein Rabatt auf ein Produkt angewandt wird, verwenden wir eine CASE WHEN Erklärung, um ihn zu berücksichtigen. SELECT order_id, product_id, unit_price, quantity, SUM(CASE -- 20% discount for this product WHEN product_id = 3143 THEN unit_price*quantity*0.8 -- 40% discount for this product WHEN product_id = 3106 THEN unit_price*quantity*0.6 ELSE unit_price*quantity END) OVER(PARTITION BY order_id, product_id) AS order_product_total_with_discount, SUM(CASE -- 20% discount for this product WHEN product_id = 3143 THEN unit_price*quantity*0.8 -- 40% discount for this product WHEN product_id = 3106 THEN unit_price*quantity*0.6 ELSE unit_price*quantity END) OVER(PARTITION BY order_id) AS order_total_with_discount FROM order_items; ORDER_IDPRODUCT_IDUNIT_PRICEQUANTITYORDER_PRODUCT_TOTAL_WITH_DISCOUNTORDER_TOTAL_WITH_DISCOUNT 2354310648611756.844916.2 2354311496.8434162.444916.2 235431237947371344916.2 235431294147192744916.2 235431392148100844916.2 235431431653678.444916.2 23543150175898644916.2 235431633061183044916.2 235431653764236844916.2 235431675168346844916.2 23543170145.2701016444916.2 23543176113.3728157.644916.2 235431826177469744916.2 2355228946200920094513.5 23552308571851054594513.5 2355231186.918816337.294513.5 2355232219188357294513.5 2355232317190323094513.5 235523261.1192211.294513.5 235523301.1197216.794513.5 2355233925199497594513.5 23552359226.620446226.494513.5 Um den Gesamtbetrag pro Produkt in einer Bestellung zu berechnen, verwenden wir die folgende Syntax: SUM(CASE WHEN product_id=3143 THEN unit_price*quantity*0.8 -- 20% discount WHEN product_id=3106 THEN unit_price*quantity*0.6 -- 40% discount ELSE unit_price*quantity END) OVER(PARTITION BY order_id, product_id) AS order_product_total_with_discount Wir übergeben die Anweisung CASE WHEN als Argument an die Funktion SUM(); wenn die Produkt-ID der aktuellen Zeile 3143 ist, dann wenden wir einen Rabatt von 20 % an; für die Produkt-ID 3106 beträgt der Rabatt 40 %. Als Nächstes partitionieren wir den Datensatz nach Bestell-ID und Produkt-ID, um die Gesamtwerte für jedes Produkt in einer Bestellung zu erhalten. Beachten Sie, dass wir zwei verschiedene PARTITION BY Klauseln in der Abfrage verwenden. Um den Gesamtwert des Produkts zu berechnen, partitionieren wir den Datensatz nach Bestell-ID und Produkt-ID. Um den Gesamtwert pro Bestellung zu berechnen, partitionieren wir den Datensatz nur nach der Bestell-ID. Der Gesamtwert der Bestellung ist für alle Zeilen mit der gleichen Bestell-ID gleich. Das heißt, wenn Sie alle Produktgesamtwerte einer bestimmten Bestellung zusammenzählen, erhalten Sie den Gesamtwert der Bestellung. Für die Bestell-ID 2355 ergibt sich zum Beispiel Folgendes: 9200 + 10545 + 16337.2 + 3572 + 3230 + 211.2 + 216.7 + 4975 + 46226.4 = 94513.5. Hier sind einige Beispiele für die Funktion SUMME() mit CASE WHEN. Weiter und SUM() mit OVER() und PARTITION BY Da Sie nun wissen, wie die Fensterfunktion SUMME() und ihre verschiedenen Syntaxoptionen verwendet werden, können Sie sie selbst ausprobieren. Wir haben Beispiele für die Berechnung des prozentualen Anteils eines einzelnen Zeilenwerts an der Gesamtsumme der Partition vorgestellt und gezeigt, wie man die laufende Summe und die benutzerdefinierte Auftragssumme berechnet. Wir ermutigen Sie, mit Ihren eigenen Daten zu üben. Wenn Sie mehr erfahren möchten, besuchen Sie unseren interaktiven Fensterfunktionen Kurs, in dem alle Konzepte der Fensterfunktionen im Detail erklärt werden. Oder schauen Sie sich unser Fensterfunktionen Cheat Sheet an, wenn Sie eine schnelle und einfache Referenz für SQL-Fensterfunktionen benötigen. Viel Erfolg! Tags: Window Functions