Data Query Language
Einführung
Die Data Query Language (kurz DQL) der Structured Query Language (kurz SQL) ermöglicht mittels Abfragen Informationen aus unterschiedlichen Tabellen zusammenzutragen. Das Ergebnis einer Abfrage ist eine Relation und kann oft auch wie eine Tabelle angezeigt, bearbeitet und weiterverwendet werden. Abfragen basieren auf den Operationen der relationalen Algebra. Wie Abfragen in SQL erstellt werden, wird anhand des folgenden Beispiels verdeutlicht.
Datenbasis
Um die Syntax von SQL-Abfragen nachvollziehen zu können, wird eine Datenbasis bereitgestellt. Das Entity Relationship Modell liefert eine Übersicht aller vorliegenden Tabellen (anklicken für größere Darstellung).
Auswahl
Eine Abfrage beginnt mit der Auswahl anzuzeigender Spalten. Die Auswahl der Spalten wird durch das Schlüsselwort SELECT eingeleitet. Nach dem Schlüsselwort SELECT folgen die Spalten, die aus einer oder mehreren Tabellen ausgewählt bzw. angezeigt werden sollen. Jede Spalte wird mit einem Komma (,) getrennt. Alternativ können auch alle Spalten einer Tabelle durch ein Sternchen * ausgewählt werden. Werden Spalten unterschiedlicher Tabellen ausgewählt, muss vor dem Spaltennamen der Tabellenname genannt werden. Tabellenname und zugehöriger Spaltenname werden durch einen Punkt (.) miteinander verbunden.
SELECT IdMitarbeiter, Mitarbeiternr, Nachname ....
Alias
Nach jeder Spalte kann mit dem Schlüsselwort AS ein neuer Name (Alias) für die Spalte festgelegt werden.
SELECT Nachname as Mitarbeitername, IdMitarbeiter ...
Datenherkunft
Nach dem Schlüsselwort FROM werden alle Tabellen angegeben, die von der Abfrage betroffen sind. Hier wird also die Datenbasis ausgewählt von der Daten ausgewählt und angezeigt werden sollen. Es muss mindestens eine Tabelle angegeben werden. Werden mehrere Tabellen ausgewählt, müssen diese durch Kommas (,) getrennt werden.
Werden im From-Teil mehrere Tabellen ausgewählt, ist bei der Bestimmung von Spalten folgendes zu beachten. Vor dem Spaltennamen muss immer der zugehörige Tabellenname genannt werden. Spaltenname und Tabellenname werden durch einen Punkt (.) verbunden. Dies betrifft die Auswahl von Spalten durch SELECT und das Definieren von Filtern durch WHERE, die Bestimmung der Sortierreihenfolge durch ORDER BY und das erstellen von Verbünden durch JOINS.
Einfache Abfrage:
SELECT * FROM Mitarbeiter
Ergebnis:
Einfache Abfrage mit Spaltenauswahl:
SELECT nachname, vorname FROM Mitarbeiter
Ergebnis:
Abfragen mit Umbenennung
SELECT IdMitarbeiter AS Mitarbeiternr, Nachname FROM Mitarbeiter
Ergebnis:
Filter
Ein Filter ermöglicht, dass nur bestimmte Zeilen bzw. Datensätze angezeigt werden. Diese Einschränkung der Anzeige nennt man Filter. Ein Filter wird durch das Schlüsselwort WHERE eingeleitet. Dann wird eine Aussage definiert. Es werden nur Datensätze angezeigt, für die diese Aussage im Sinne der booleschen Algebra WAHR bzw. gültig ist. Teilaussagen können durch die Schlüsselwörter AND bzw. OR und NOT zu einer komplexeren Gesamtaussage kombiniert werden. Neben den Operatoren <> und = kann auch between einegsetzt werden. Mit between kann man die Ober- und Untergrenze eines Filters auf einmal angeben
Abfragen mit einfachem Filter
SELECT Vorname, Nachname FROM Mitarbeiter WHERE Nachname= 'Krause'
Ergebnis:
Nachname
Krause
Krause
Vorname
Sabine
Christoph
Abfragen mit komplexerem Filter
SELECT Vorname, Nachname FROM Mitarbeiter WHERE ((Nachname= 'Krause'OR Vorname = 'Manuel')AND IdMitarbeiter <> 1)
Ergebnis:
Nachname
Bitter
Krause
Vorname
Manuel
Christoph
Abfragen mit between Filter
SELECT Vorname, Nachname FROM Mitarbeiter WHERE Geburtsdatum BETWEEN '01-JAN-71' AND '10-JAN-71'
IS NULL
SQL ermöglicht die Verwendung von NULL-Werten, die mit dem IS NULL Befehl abgefragt werden können. Dies ist insbesondere wichtig bei der Bildung von äußeren Verbünden, die eine Relation erzeugen, die alle Werte der einen Relation enthalten, sowie alle Werte der anderen, für die die Verbundbedingung wahr ist, sonst eben NULL-Werte. Die Prüfung, ob ein Wert null ist liefert die booleschen Werte true oder false zurück. Im Sinne der booleschen Algebra lässt sich die Aussage durch das Schlüsselwort not auch verneinen.
Spaltenname is [not] null
Beispiel
SELECT * FROM Termin WHERE Datum IS NOT NULL
Sortierung
Mit Hilfe der Schlüsselwörter ORDER BY kann die Reihenfolge der anzuzeigenden Datensätze bestimmt werden. Nach ORDER BY werden die Spalten aufgelistet nach denen das Abfrageergebnis sortiert werden soll. Die zu sortierenden Spalten werden durch Kommas getrennt. Über die Schlüsselwörter ASC (ASCENDING / aufsteigend) und DESC (DESCENDING / absteigend) kann die Reihenfolge je Spalte zusätzlich definiert werden.
SELECT Nachname, Vorname FROM Mitarbeiter ORDER BY Nachname ASC
Ergebnis:
Top-N-Zeilen abfragen
Top-N-Abfragen sind Abfragen, die das Ergebnis auf eine bestimmte Zeilenzahl beschränken. Das sind häufig Abfragen nach den aktuellsten oder „besten“ Einträgen. Idealerweise wird die Abfrage mit ORDER BY kombiniert, um eine bestimmte Anzahl an relevanten Datensätzen zu erhalten.
Bei MySQL und PostgreSQL kann man die gewünschte Zeilenzahl durch die limit-Klausel beschränken. Bei anderen Datenbanken werden andere Befehle verwende .
SELECT * FROM Warenkorb ORDER BY datum DESC LIMIT 10
Tabellen Verknüpfen
Werden Informationen unterschiedlicher Tabellen in einer Abfrage zusammengefügt, müssen diese Tabellen verbunden werden. Die Datenquelle wird wie oben beschrieben durch das Schlüsselwort FROM eingeleitet und dann festgelegt. Die Tabellennamen werden durch Kommas getrennt. Danach können mit Hilfe sogenannter JOINs mehrere Tabellen über Schlüsselfelder miteinander verknüpft werden, so dass Daten aus verschiedenen Tabellen zusammengeführt und angezeigt werden.
Innerer natürlicher Verbund (INNER JOIN)
Möchte man zwei oder mehrere Tabellen miteinander Verbinden und Datensätze aller Tabellen anzeigen für die ein Kriterium übereinstimmt, verwendet man den inneren natürlichen Verbund.
Abbildung INNER JOIN
Hierfür kann man einen normalen Filter verwenden. Nach dem Schlüsselwort WHERE werden zwei Spaltennamen von zwei Tabellen mit einem Gleichheitszeichen verglichen. Es werden alle Datensätze der beiden Tabellen angezeigt für die diese beiden Bedingungen gleich sind. In der Abbildung Inner Join werden diese relevanten Datensätze durch eine blaue Fläche dargestellt.
Alternativ kann folgende Syntax verwendet werden. Nach dem Schlüsselwort FROM folgt der Tabellenname der ersten Tabelle. Dann folgen die Schlüsselwörter INNER JOIN. Dann folgt der zweite Tabellenname. Nun muss das Schlüsselwort ON genannt werden. Wie bei einem Filter werden nun die beiden Spalten genannt für die eine Übereinstimmung gelten soll.
Abfrage Innerer natürlicher Verbund mit WHERE
SELECT Salon.IdSalon, Salon.Name AS Salonname, Mitarbeiter.Nachname, Mitarbeiter.Vorname FROM Salon, Mitarbeiter WHERE Salon.IdSalon= Mitarbeiter.FKSalon
Abfrage Innerer natürlicher Verbund mit INNER JOIN
SELECT Salon.IdSalon, Salon.Name AS Salonname, Mitarbeiter.Nachname, Mitarbeiter.Vorname FROM Salon INNER JOIN Mitarbeiter ON Salon.IdSalon= Mitarbeiter.FKSalon
Ergebnis für beide Abfragen
Innere natürlicher Verbund über mehrere Tabellen
Möchte man eine dritte Tabelle in den Verbund aufnehmen, dann kann man diese einfach über einen weiteren INNER JOIN hinzufügen. Die Reihenfolge der Tabellen in dem Statement ist nicht von Bedeutung.
SELECT Salon.IdSalon, Salon.Name AS Salonname, Mitarbeiter.Nachname, Mitarbeiter.Vorname, Termin.Datum FROM Salon INNER JOIN Mitarbeiter ON Salon.IdSalon= Mitarbeiter.FKSalon INNER JOIN Termin ON Termin.fkMitarbeiter= Mitarbeiter.IDMitarbeiter
Ergebnis für die erweiterte Abfrage
Linker äußerer Verbund (LEFT JOIN)
LEFT bezieht sich auf die in der SQL-Anweisung Links von den Schlüsselwörtern LEFT JOIN stehenden Tabellennamen. Die Daten dieser Tabelle werden ALLE angezeigt. Die Datensätze der rechten Tabelle werden nur Angezeigt, wenn sie dem Filterkriterium genügen. Die Reihenfolge in der die Tabellen genannt werden ist also entscheidend!
Abfrage linker äußerer Verbund
SELECT Salon.IdSalon, Salon.Name AS Salonname, Mitarbeiter.Nachname, Mitarbeiter.Vorname FROM Salon LEFT JOIN Mitarbeiter ON Salon.IdSalon= Mitarbeiter.FKSalon
Ergebenis
Rechter äußerer Verbund (RIGHT JOIN)
Der RIGHT JOIN funktioniert genau wie der LEFT JOIN, nur in diesem Fall ist alles umgedreht. Beim RIGHT JOIN werden die Einträge der rechten Tabelle selektiert, auch wenn keine Verbindung zu den Daten der linken Tabelle besteht. Auch hier ist die Reihenfolge in der die Tabellen genannt werden entscheidend!
Abbildung RIGHT JOIN
Abfrage rechter äußerer Verbund
SELECT Salon.IdSalon, Salon.Name AS Salonname, Mitarbeiter.Nachname, Mitarbeiter.Vorname FROM Mitarbeiter RIGHT JOIN SALON ON Mitarbeiter.FKSalon = Salon.IdSalon;
Ergebenis
Gruppierung mit Aggregat-Funktionen
Mit Hilfe des Schlüsselwortes GROUP BY können Datensätze aggregiert werden. GROUP BY steht am Ende einer SQL-Anweisung und listet die Spalten auf, die für eine Abfrage aggregiert werden sollen. Es sollten also die Spalten die im SELECT-Bereich aufgeführt werden bei der Gruppierung berücksichtigt werden. Zusätzlich muss in der SQL-Anweisung definiert werden, wie die Datensätze zu aggregieren sind. In diesem Zusammenhang gibt es mehrere Möglichkeiten. Z.B. lässt sich mit dem Schlüsselwort COUNT, die Anzahl der Datensätze bestimmen. Hierfür ist noch eine Spalte an die COUNT-Funktion zu übergeben, dessen Werte gezählt werden können. Die Spalte selbst wird in runden Klammern () direkt hinter das Schlüsselwort geschrieben.
Alternativ lassen sich so auch Summen (SUM), Mittelwerte (AVG), minimaler Wert (MIN), maximaler Wert (MAX), etc. bilden. Hierfür ist das Schlüsselwort COUNT zu ersetzen.
Abfrage gruppiert mit COUNT-Funktion
SELECT COUNT(Termin.TerminID) AS AnzahlTermine, Mitarbeiter.Nachname AS Mitarbeiter FROM TERMIN RIGHT JOIN Mitarbeiter ON Termin.FKMitarbeiter = Mitarbeiter.MitarbeiterID GROUP BY Mitarbeiter.MitarbeiterID
Ergebnis
Möchte man die Datensätze im Sinne eines Filters in einer gruppierten Abfrage einschränken, muss man das Schlüsselwort HAVING anstatt WHERE verwenden. Der so definierte Filter bezieht sich dann auf die durch GROUP BY aggregierten Spalten.
Abfrage gruppiert mit SUM-Funktion und Having
SELECT SUM(Termin.Rechnungsbetrag) AS Umsatz, Mitarbeiter.Nachname AS Mitarbeiter FROM TERMIN INNER JOIN Mitarbeiter ON Termin.FKMitarbeiter = Mitarbeiter.MitarbeiterID GROUP BY Mitarbeiter.MitarbeiterID HAVING Umsatz >100;
Ein Filter mit WHERE wäre hier nicht möglich, da sich die Spalte Umsatz teil der Berechnung und damit der Gruppierung ist. Auch ein Filter auf die Spalte MitarbeiterID wäre nur mit HAVING möglich, da auch diese von der Gruppierung betroffen ist.
Ergebnis
Umsatz
106
Mitarbeiter
Schrotter
Unterabfragen/Verschachtelte Abfragen
Immer wieder werden zur Durchführung einer Abfrage oder eines anderen Befehls Informationen benötigt, die zuerst durch eine separate Abfrage bereitgestellt werden müssen. Solche „Unterabfragen“ werden hier behandelt.
Wenn eine Abfrage als Ergebnis einen einzelnen Wert liefert, kann sie anstelle eines Wertes benutzt werden.
Wenn eine Abfrage eine Ergebnismenge, also etwas in Form von Relationen liefert, kann sie anstelle einer Tabelle benutzt werden.
Quelle https://public.urz.uni-heidelberg.de/
Bitte beachten Sie, dass die Unterabfrage immer in Klammern gesetzt wird. Auch wenn ein DBMS das nicht verlangen sollte, ist es wegen der Übersichtlichkeit dringend zu empfehlen. Häufig werden Ergebnisse von Aggregatfunktionen als Teil der WHERE-Klausel benötigt. So zum Beispiel für Folgende Aufgabenstellung:
Zeige die Termine mit unterdurchschnittlichen Umsatz an!
Lösung Teil 1: Berechne die durchschnittliche Umsatzhöhe aller Termine.
Lösung Teil 2: Übernimm das Ergebnis als Vergleichswert in die eigentliche Abfrage.
Abfrage mit Unterabfrage
SELECT TerminID, Rechnungsbetrag FROM Termin WHERE Rechnungsbetrag < ( SELECT AVG(Rechnungsbetrag ) FROM Termin);
Ergebnis
UNION
Mit UNION kann man zwei Relationen mit einander vereinen. Doppelte Werte werden dabei ignoriert. Hierfür muss man zwei SELECT Abfragen durch das Schlüsselwort UNION miteinander verbinden. Bei UNION muss man darauf achten, dass die selektierten Spalten beider Tabellen vom gleichen Typ sind. Die SELECT Abfragen können komplex und verschachtelt sein und Filter beinhalten.
UNION Syntax
SELECT spalten_name FROM tabelle1 UNION SELECT spalten_name FROM tabelle2
Beispiel
Durch folgendes Beispiel kann man sich eine Vereinigung aller Personen aus den Tabellen Kunde und Mitarbeiter ausgeben lassen.
SELECT Mitarbeiter.IdMitarbeiter AS ID, Mitarbeiter.nachname , Mitarbeiter.vorname FROM Mitarbeiter UNION SELECT Kunde.IdKunde as ID, Kunde.nachname , Kunde.vorname FROM Kunde;
Angezeigt wird folgende Relation. Die ersten fünf Datensätze entstammen aus der Tabelle Mitarbeiter und die letzten fünf aus der Tabelle Kunde.
Reihenfolge der Abarbeitung
Die DQL- Abfragen werden vom Datenbank-Management-System in einer bestimmten Reihenfolge aufgelöst und abgearbeitet. Grundsätzlich gilt, dass eine Abfrage von innen nach außen aufgelöst wird:
FROM-Teil inklusive JOINs abgearbeitet.
Filterung durch WHERE
Gruppierung durch GROUP BY
Filterung von Gruppen durch HAVING
Selektieren und Aggrigieren durch SELECT und Formeln wie SUM()
Sortieren durch ORDER BY
Auswahl relavanter Datensätze mit Limit