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).

(Bitte 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 Zeilen­zahl 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!

Abbildung LEFT JOIN

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.

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!

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: