Keine Bearbeitungszusammenfassung
Zeile 1: Zeile 1:
Die '''Data Query Language (DQL)''' ermöglicht es, Informationen aus verschiedenen Tabellen abzufragen. Das Ergebnis ist eine Relation, die meist als Tabelle angezeigt wird.
== Einführung ==
Die '''Data Query Language''' (kurz '''DQL''') der [[SQL|Structured Query Language (SQL)]] ermöglicht es, 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'''.


== Datenbasis ==
== Datenbasis ==
[[Datei:DQLDatenbasisERM.jpg|mini|ERM-Modell zur Datenbasis]]
[[Datei:DQLDatenbasisERM.jpg|mini|ERM-Modell zur Datenbasis]]
[[Datei:DQLDatenbasisTabellen.jpg|mini]]
[[Datei:DQLDatenbasisTabellen.jpg|mini|Tabellenübersicht]]
Um die Syntax von SQL-Abfragen nachvollziehen zu können, wird eine Datenbasis bereitgestellt. Das Entity Relationship Modell liefert eine Übersicht aller vorliegenden Tabellen (siehe Bilder).
Um die Syntax von SQL-Abfragen nachvollziehen zu können, wird die Datenbasis eines Friseursalons verwendet (siehe Bilder). Die Abfragen beziehen sich auf Tabellen wie `Mitarbeiter`, `Salon`, `Kunde` und `Termin`.


== Grundlegende Abfragen ==
== Auswahl (SELECT) ==
Eine Abfrage beginnt mit der Auswahl anzuzeigender Spalten durch das Schlüsselwort '''SELECT'''.
* Spalten werden durch Komma getrennt.
* Mit einem Sternchen (`*`) werden alle Spalten ausgewählt.
* Bei mehreren Tabellen wird die Punkt-Notation verwendet: `Tabellenname.Spaltenname`.
 
=== Alias (AS) ===
Nach jeder Spalte kann mit dem Schlüsselwort '''AS''' ein neuer Name (Alias) für die Anzeige festgelegt werden.


=== Einfache Abfrage (Projektion) ===
<syntaxhighlight lang="sql">
SELECT IdMitarbeiter AS Mitarbeiternr, Nachname FROM Mitarbeiter;
</syntaxhighlight>
 
== Datenherkunft (FROM) ==
Nach dem Schlüsselwort '''FROM''' werden alle Tabellen angegeben, die von der Abfrage betroffen sind. Es muss mindestens eine Tabelle angegeben werden.
 
'''Einfache Abfrage:'''
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
SELECT * FROM Mitarbeiter;
SELECT * FROM Mitarbeiter;
</syntaxhighlight>
</syntaxhighlight>
'''Ergebnis:'''
'''Ergebnis:'''
{| class="wikitable"
{| class="wikitable"
Zeile 27: Zeile 43:
|}
|}


=== Alias und Spaltenauswahl ===
== Filter (WHERE) ==
Ein Filter schränkt die Ergebnismenge auf Datensätze ein, für die eine Aussage im Sinne der '''booleschen Algebra''' wahr ist. Er wird durch '''WHERE''' eingeleitet.
 
* '''Operatoren:''' `<>`, `=`, `AND`, `OR`, `NOT`.
* '''BETWEEN:''' Gibt Ober- und Untergrenze eines Filters gleichzeitig an.
 
'''Beispiel komplexer Filter:'''
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
SELECT IdMitarbeiter AS Mitarbeiternr, Nachname FROM Mitarbeiter;
SELECT Vorname, Nachname FROM Mitarbeiter  
WHERE (Nachname = 'Krause' OR Vorname = 'Manuel') AND IdMitarbeiter <> 1;
</syntaxhighlight>
</syntaxhighlight>
'''Ergebnis:'''
'''Ergebnis:'''
{| class="wikitable"
{| class="wikitable"
! Mitarbeiternr !! Nachname
! Vorname !! Nachname
|-
|-
| 1 || Krause
| Christoph || Krause
|-
|-
| 2 || Schrotter
| Manuel || Bitter
|-
| 3 || Hermann
|-
| 4 || Krause
|-
| 5 || Bitter
|}
|}


== Filtern von Daten (WHERE) ==
=== IS NULL ===
SQL nutzt '''NULL-Werte''' für fehlende Daten. Die Prüfung erfolgt mit `IS NULL` oder `IS NOT NULL`.
<syntaxhighlight lang="sql">
SELECT * FROM Termin WHERE Datum IS NOT NULL;
</syntaxhighlight>
 
== Sortierung und Begrenzung ==
 
=== ORDER BY ===
Mit '''ORDER BY''' wird die Sortierreihenfolge festgelegt.
* '''ASC:''' aufsteigend (Standard)
* '''DESC:''' absteigend


=== Einfacher Filter ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
SELECT Vorname, Nachname FROM Mitarbeiter WHERE Nachname = 'Krause';
SELECT Nachname, Vorname FROM Mitarbeiter ORDER BY Nachname ASC;
</syntaxhighlight>
</syntaxhighlight>
'''Ergebnis:'''
{| class="wikitable"
! Vorname !! Nachname
|-
| Sabine || Krause
|-
| Christoph || Krause
|}


=== Komplexer Filter ===
=== Top-N-Zeilen (LIMIT) ===
Bei MySQL und PostgreSQL wird die Ergebnismenge durch '''LIMIT''' beschränkt, um z. B. nur die "besten" oder aktuellsten Einträge zu erhalten.
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
SELECT Vorname, Nachname FROM Mitarbeiter
SELECT * FROM Warenkorbposition ORDER BY Datum DESC LIMIT 10;
WHERE (Nachname = 'Krause' OR Vorname = 'Manuel') AND IdMitarbeiter <> 1;
</syntaxhighlight>
</syntaxhighlight>
'''Ergebnis:'''
{| class="wikitable"
! Vorname !! Nachname
|-
| Christoph || Krause
| Manuel || Bitter
|}


== Tabellen verknüpfen (JOINs) ==
== Tabellen verknüpfen (JOINs) ==
Werden Informationen aus unterschiedlichen Tabellen benötigt, müssen diese verbunden werden.


Hier werden die Tabellen `Salon` (Tabelle A) und `Mitarbeiter` (Tabelle B) verknüpft.
=== Innerer natürlicher Verbund (INNER JOIN) ===
 
Zeigt nur Datensätze an, für die in beiden Tabellen eine Entsprechung existiert.
=== Inner Join (Schnittmenge) ===
<html>
<html>
<svg width="200" height="120" viewBox="0 0 200 120">
<svg width="200" height="120" viewBox="0 0 200 120">
Zeile 87: Zeile 100:
   </clipPath>
   </clipPath>
   <circle cx="130" cy="60" r="50" fill="#3498db" clip-path="url(#inner)" />
   <circle cx="130" cy="60" r="50" fill="#3498db" clip-path="url(#inner)" />
   <text x="45" y="65" font-size="12">A</text>
   <text x="45" y="65" font-size="12">Tab. A</text>
   <text x="145" y="65" font-size="12">B</text>
   <text x="135" y="65" font-size="12">Tab. B</text>
</svg>
</svg>
</html>
</html>


<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
SELECT Salon.Name, Mitarbeiter.Nachname  
SELECT Salon.Name AS Salonname, Mitarbeiter.Nachname  
FROM Salon INNER JOIN Mitarbeiter ON Salon.IdSalon = Mitarbeiter.FKSalon;
FROM Salon INNER JOIN Mitarbeiter ON Salon.IdSalon = Mitarbeiter.FKSalon;
</syntaxhighlight>
</syntaxhighlight>
'''Ergebnis:''' (Salon 3 erscheint nicht, da kein Mitarbeiter zugeordnet ist)
{| class="wikitable"
! Name !! Nachname
|-
| Friedrich List Frisuren || Krause
|-
| Friedrich List Frisuren || Schrotter
|-
| Friedrich List Frisuren || Hermann
|-
| Hammer Haare || Krause
|-
| Hammer Haare || Bitter
|}


=== Left Join (Inklusive linker Tabelle) ===
=== Linker äußerer Verbund (LEFT JOIN) ===
Alle Datensätze der linken Tabelle werden angezeigt, die der rechten nur bei Übereinstimmung.
<html>
<html>
<svg width="200" height="120" viewBox="0 0 200 120">
<svg width="200" height="120" viewBox="0 0 200 120">
   <circle cx="130" cy="60" r="50" stroke="black" stroke-width="2" fill="white" />
   <circle cx="130" cy="60" r="50" stroke="black" stroke-width="2" fill="white" />
   <circle cx="70" cy="60" r="50" stroke="black" stroke-width="2" fill="#3498db" />
   <circle cx="70" cy="60" r="50" stroke="black" stroke-width="2" fill="#3498db" />
   <text x="45" y="65" font-size="12">A</text>
   <text x="45" y="65" font-size="12">Tab. A</text>
   <text x="145" y="65" font-size="12">B</text>
   <text x="135" y="65" font-size="12">Tab. B</text>
</svg>
</svg>
</html>
</html>


<syntaxhighlight lang="sql">
=== Rechter äußerer Verbund (RIGHT JOIN) ===
SELECT Salon.Name, Mitarbeiter.Nachname
Alle Einträge der rechten Tabelle werden selektiert, auch ohne Verbindung zur linken.
FROM Salon LEFT JOIN Mitarbeiter ON Salon.IdSalon = Mitarbeiter.FKSalon;
</syntaxhighlight>
'''Ergebnis:''' (Salon 3 wird mit NULL aufgeführt)
{| class="wikitable"
! Name !! Nachname
|-
| Friedrich List Frisuren || Krause
|-
| Friedrich List Frisuren || Schrotter
|-
| Friedrich List Frisuren || Hermann
|-
| Hammer Haare || Krause
|-
| Hammer Haare || Bitter
|-
| Kaiserschnitt || ''NULL''
|}
 
=== Right Join (Inklusive rechter Tabelle) ===
<html>
<html>
<svg width="200" height="120" viewBox="0 0 200 120">
<svg width="200" height="120" viewBox="0 0 200 120">
   <circle cx="70" cy="60" r="50" stroke="black" stroke-width="2" fill="white" />
   <circle cx="70" cy="60" r="50" stroke="black" stroke-width="2" fill="white" />
   <circle cx="130" cy="60" r="50" stroke="black" stroke-width="2" fill="#3498db" />
   <circle cx="130" cy="60" r="50" stroke="black" stroke-width="2" fill="#3498db" />
   <text x="45" y="65" font-size="12">A</text>
   <text x="45" y="65" font-size="12">Tab. A</text>
   <text x="145" y="65" font-size="12">B</text>
   <text x="135" y="65" font-size="12">Tab. B</text>
</svg>
</svg>
</html>
</html>
== Gruppierung und Aggregat-Funktionen ==
Mit '''GROUP BY''' werden Datensätze aggregiert.
* '''Funktionen:''' `COUNT`, `SUM`, `AVG`, `MIN`, `MAX`.
* '''HAVING:''' Filtert aggregierte Gruppen (ein `WHERE` ist hier nicht möglich).


<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
SELECT Salon.Name, Mitarbeiter.Nachname  
SELECT SUM(Rechnungsbetrag) AS Umsatz, Mitarbeiter.Nachname  
FROM Salon RIGHT JOIN Mitarbeiter ON Salon.IdSalon = Mitarbeiter.FKSalon;
FROM Termin INNER JOIN Mitarbeiter ON Termin.FKMitarbeiter = Mitarbeiter.IdMitarbeiter
GROUP BY Mitarbeiter.IdMitarbeiter HAVING Umsatz > 100;
</syntaxhighlight>
</syntaxhighlight>
'''Ergebnis:''' 106 | Schrotter (Da Claudia Schrotter Termine über 29€ und 77€ hatte).


== Gruppierung und Aggregate ==
== Unterabfragen (Verschachtelt) ==
Unterabfragen liefern Informationen, die als Grundlage für die Hauptabfrage dienen. Sie müssen immer in Klammern gesetzt werden.
<syntaxhighlight lang="sql">
-- Termine mit unterdurchschnittlichem Umsatz
SELECT TerminID, Rechnungsbetrag FROM Termin
WHERE Rechnungsbetrag < (SELECT AVG(Rechnungsbetrag) FROM Termin);
</syntaxhighlight>


== UNION ==
Mit '''UNION''' werden zwei Relationen vereint. Doppelte Werte werden ignoriert. Die Spalten müssen vom gleichen Typ sein.
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
SELECT SUM(Rechnungsbetrag) AS Umsatz, Mitarbeiter.Nachname
SELECT nachname FROM Mitarbeiter UNION SELECT nachname FROM Kunde;
FROM Termin
INNER JOIN Mitarbeiter ON Termin.FKMitarbeiter = Mitarbeiter.IdMitarbeiter
GROUP BY Mitarbeiter.IdMitarbeiter
HAVING Umsatz > 100;
</syntaxhighlight>
</syntaxhighlight>
'''Ergebnis:'''
 
== Reihenfolge der Abarbeitung ==
Das DBMS arbeitet eine DQL-Abfrage logisch von "innen nach außen" in dieser Reihenfolge ab:
 
{| class="wikitable"
{| class="wikitable"
! Umsatz !! Mitarbeiter
! Schritt !! Klausel !! Beschreibung
|-
| 1 || '''FROM''' || Inklusive JOINs: Datenbasis festlegen.
|-
| 2 || '''WHERE''' || Filterung der einzelnen Datensätze.
|-
| 3 || '''GROUP BY''' || Gruppierung der Daten.
|-
| 4 || '''HAVING''' || Filterung der gebildeten Gruppen.
|-
| 5 || '''SELECT''' || Projektion und Berechnungen (SUM, etc.).
|-
| 6 || '''ORDER BY''' || Sortierung des Ergebnisses.
|-
|-
| 106 || Schrotter
| 7 || '''LIMIT''' || Auswahl der relevanten Datensatzzahl.
|}
|}
''(Berechnung: Claudia Schrotter [ID 2] hatte Termine über 29 und 77 Euro.)''


[[Kategorie:Datenbanken]]
[[Kategorie:Datenbanken]]
[[Kategorie:FI_I_SDM]]
[[Kategorie:FI_I_SDM]]
[[Kategorie:FI_I_TP2]]
[[Kategorie:FI_I_TP2]]
Abgerufen von „https://wiki.flbk-hamm.de/DQL