SQL-Handout

Werbung
150.422
5
Datenbanken – SQL Handout 3
SS 2017
Subqueries
• Subqueries • werden verwendet, um das Ergebnis einer inneren Abfrage in der äußeren Abfrage zu verwenden. Im einfachsten Fall gibt die innere Abfrage einen einzelnen Wert zurück, der als Konstante in der äußeren
Abfrage verwendet wird.
B Beispiele. Welcher Lieferant bietet den kleinsten Preis für Teil KT12AB321?
SELECT S_No FROM Order_Options
WHERE P_No = ’ KT12AB321 ’
AND Price_per_Unit =
( SELECT MIN ( Price_per_Unit ) FROM Order_Options
WHERE P_No = ’ KT12AB321 ’)
Die innere Abfrage bestimmt den minimalen Preis für Teil KT12AB321. Die äußere Abfrage sucht alle Supplier,
die Teil KT12AB321 zum minimalen Preis anbieten. Man beachte, dass die innere Abfrage einen einzelnen Wert
zurückgeben muss. Die äußere Abfrage könnte auch mehrere Werte zurückgeben, falls mehrere Lieferanten
zum günstigsten Preis anbieten.
Zeige alle Bestellungen, deren Wert höher ist als der von Bestellung 1-290605-1.
SELECT * FROM Orders
WHERE Price_per_Unit * No_of_Units_ordered >
( SELECT Price_per_Unit * No_of_Units_ordered FROM Orders
WHERE O_No = ’ 1 -290605 -1 ’)
Regel: Bei Vergleichen mit =, > etc. müssen innere Abfragen genau einen einzelnen Wert zurückgeben!
Allerdings gibt es auch die Möglichkeit zu überprüfen, ob ein Element in einer Liste von Werten vorkommt.
Dies lässt sich mit IN bewerkstelligen, das auch in Kombination mit einer Subquery verwendet werden kann.
B Beispiele. Zeige die Lieferanten mit den Nummern 3, 5 und 11.
SELECT * FROM Supplier
WHERE S_No IN (3 , 5 , 11)
Zeige alle Angebote von Lieferant 1 aus Order Options.
SELECT * FROM Order_Options
WHERE P_No IN
( SELECT P_No FROM Order_Options
WHERE S_No = 1)
Eine innere Abfrage, die einen einzelnen Wert zurückgibt, kann an jeder Stelle statt einer Konstanten verwendet
werden.
B Beispiel. Zeige für jedes Angebot für Teil KT12AB321 in Order Options die Differenz zum günstigsten
Preis.
SELECT * ,
Price_per_Unit - ( SELECT MIN ( Price_per_Unit ) FROM Order_Options
WHERE P_No = ’ KT12AB321 ’) AS Differenz
FROM Order_Options
WHERE P_No = ’ KT12AB321 ’
• Subqueries als Tabellen •
Neben der Möglichkeit, mit IN auf eine Liste von Werten abzufragen, kann das Ergebnis einer Subquery in
der äußeren Abfrage auch wie eine Tabelle verwendet werden. In diesem Fall steht die Subquery entsprechend
im FROM-Teil der äußeren Abfrage.
B Beispiel. Bestimme den höchsten Durchschnittspreis (pro Einheit) eines Teils in Order Options.
SELECT MAX ( avg_p ) FROM
( SELECT P_No , AVG ( Price_per_Unit ) AS avg_p FROM Order_Options
GROUP BY P_No ) AS new_table
Regel: Bei Abfragen im FROM muss der inneren Abfrage mit AS ein Name zugewiesen werden!
• Vergleich von Tupeln in Subqueries •
Im allgemeinen lassen sich in SQL auch Tupel von Werten (also z.B. mehrere Spalten gleichzeitig) miteinander
vergleichen.
B Beispiel. Zeige alle Lieferanten in Supplier, die dieselbe Evaluierung und denselben Vertragsstatus wie
Lieferant 1 haben.
SELECT * FROM Supplier
WHERE ( S_Evaluation , S_Contractstatus ) =
( SELECT S_Evaluation , S_Contractstatus FROM Supplier
WHERE S_No = 1)
6
UNION, MINUS und INTERSECT
• UNION, MINUS und INTERSECT • entsprechen den mengentheoretischen Verknüpfungen ∪ (Vereinigung),
\ (Differenz) und ∩ (Schnitt). Ein Beispiel zur Erinnerung: Für A = {1, 2, 3, 4} und B = {2, 4, 6} ist
A ∪ B = {1, 2, 3, 4, 6}, A \ B = {1, 3} und A ∩ B = {2, 4}. Mit UNION lässt sich das Ergebnis zweier
Abfragen vereinigen, vorausgesetzt die beiden Abfragen haben dieselbe Spaltenanzahl. In der Ergebnistabelle
sind alle doppelten Einträge automatisch gelöscht. UNION ist vor allem dann nützlich, wenn Daten aus verschiedenen Tabellen miteinander verknüpft werden sollen. Ansonsten lässt sich der Gebrauch von UNION durch
die Verwendung von OR und DISTINCT umgehen.
B Beispiel. Aus Gründen der Datenintegrität sollten alle Teile, die in Order Options vorkommen, auch in
Parts verzeichnet sein. Sollte dies nicht der Fall sein, so könnte man mit UNION alle Teile finden, die zumindest
in einer der beiden Tabellen vorkommen. In der Ergebnistabelle wird jedes Teil nur einmal gelistet, auch wenn
er in beiden Tabellen vorkommt.
( SELECT P_No FROM Parts )
UNION
( SELECT P_No FROM Order_Option )
Ein entsprechendes INTERSECT würde alle Teile ausgeben, die in beiden Tabellen vorkommen. Mit MINUS ließe
sich die Differenz berechnen, d.h. alle Teile, die in der einen Tabelle vorkommen, aber nicht in der anderen.
MySQL unterstützt MINUS und INTERSECT bisher leider nicht. Entsprechende Abfragen können mittels IN oder
über Self Joins (siehe weiter unten) in Kombination mit entsprechenden logischen Verknüpfungen simuliert
werden.
Regel: UNION funktioniert nur, wenn alle miteinander kombinierten Abfragen dieselbe Spaltenanzahl haben!
Herunterladen