Keine Bearbeitungszusammenfassung
 
(3 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
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]]
Basierend auf dem bereitgestellten Schema des Friseursalons ergeben sich folgende Tabelleninhalte:
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`.


=== Einfache Abfrage (Projektion) ===
=== Alias (AS) ===
Nach jeder Spalte kann mit dem Schlüsselwort '''AS''' ein neuer Name (Alias) für die Anzeige festgelegt werden.
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
SELECT * FROM Mitarbeiter;
SELECT Nachname AS Mitarbeitername, IdMitarbeiter FROM Mitarbeiter;
</syntaxhighlight>
</syntaxhighlight>
'''Ergebnis:'''
{| class="wikitable"
! IdMitarbeiter !! Nachname !! Vorname !! FkSalon
|-
| 1 || Krause || Sabine || 1
|-
| 2 || Schrotter || Claudia || 1
|-
| 3 || Hermann || Markus || 1
|-
| 4 || Krause || Christoph || 2
|-
| 5 || Bitter || Manuel || 2
|}


=== Alias und Spaltenauswahl ===
== 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 mit Spaltenauswahl:'''
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
SELECT IdMitarbeiter AS Mitarbeiternr, Nachname FROM Mitarbeiter;
SELECT nachname, vorname FROM Mitarbeiter;
</syntaxhighlight>
</syntaxhighlight>
'''Ergebnis:'''
'''Ergebnis:'''
{| class="wikitable"
{| class="wikitable"
! Mitarbeiternr !! Nachname
! nachname !! vorname
|-
|-
| 1 || Krause
| Krause || Sabine
|-
|-
| 2 || Schrotter
| Schrotter || Claudia
|-
|-
| 3 || Hermann
| Hermann || Markus
|-
|-
| 4 || Krause
| Krause || Christoph
|-
|-
| 5 || Bitter
| Bitter || Manuel
|}
|}


== Filtern von Daten (WHERE) ==
== 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. Neben den Operatoren `<>` und `=` kann auch '''BETWEEN''' eingesetzt werden, um Ober- und Untergrenze eines Filters gleichzeitig anzugeben.


=== Einfacher Filter ===
'''Beispiel komplexer Filter:'''
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
SELECT Vorname, Nachname FROM Mitarbeiter WHERE Nachname = 'Krause';
SELECT Vorname, Nachname FROM Mitarbeiter  
WHERE (Nachname = 'Krause' OR Vorname = 'Manuel') AND IdMitarbeiter <> 1;
</syntaxhighlight>
</syntaxhighlight>
'''Ergebnis:'''
'''Ergebnis:'''
{| class="wikitable"
{| class="wikitable"
! Vorname !! Nachname
! Vorname !! Nachname
|-
|-
| Sabine || Krause
| Christoph || Krause
|-
|-
| Christoph || Krause
| Manuel || Bitter
|}
|}


=== Komplexer Filter ===
=== IS NULL ===
SQL nutzt '''NULL-Werte''' für fehlende Informationen. Die Prüfung erfolgt mit `IS NULL` oder `IS NOT NULL`. Dies ist besonders bei äußeren Verbünden (Outer Joins) wichtig.
<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
 
<syntaxhighlight lang="sql">
SELECT Nachname, Vorname FROM Mitarbeiter ORDER BY Nachname ASC;
</syntaxhighlight>
 
=== Top-N-Zeilen (LIMIT) ===
Bei MySQL und PostgreSQL wird die Ergebnismenge durch '''LIMIT''' beschränkt, um z. B. nur die 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 unterschiedlicher Tabellen zusammengefügt, müssen diese über Schlüsselfelder 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 96:
   </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.IdSalon, 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)
'''Ergebnis:''' (Salon 3 "Kaiserschnitt" erscheint nicht, da ihm kein Mitarbeiter zugeordnet ist)
{| class="wikitable"
{| class="wikitable"
! Name !! Nachname
! IdSalon !! Salonname !! Nachname
|-
|-
| Friedrich List Frisuren || Krause
| 1 || Friedrich List Frisuren || Krause
|-
|-
| Friedrich List Frisuren || Schrotter
| 1 || Friedrich List Frisuren || Schrotter
|-
|-
| Friedrich List Frisuren || Hermann
| 1 || Friedrich List Frisuren || Hermann
|-
|-
| Hammer Haare || Krause
| 2 || Hammer Haare || Krause
|-
|-
| Hammer Haare || Bitter
| 2 || Hammer Haare || Bitter
|}
|}


=== Left Join (Inklusive linker Tabelle) ===
=== Linker äußerer Verbund (LEFT JOIN) ===
Alle Datensätze der linken Tabelle (Tab. A) werden angezeigt. Die der rechten Tabelle nur bei Übereinstimmung, sonst `NULL`.
<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">
<syntaxhighlight lang="sql">
SELECT Salon.Name, Mitarbeiter.Nachname  
SELECT Salon.Name AS Salonname, Mitarbeiter.Nachname  
FROM Salon LEFT JOIN Mitarbeiter ON Salon.IdSalon = Mitarbeiter.FKSalon;
FROM Salon  
LEFT JOIN Mitarbeiter ON Salon.IdSalon = Mitarbeiter.FKSalon;
</syntaxhighlight>
</syntaxhighlight>
'''Ergebnis:''' (Salon 3 wird mit NULL aufgeführt)
'''Ergebnis:'''
{| class="wikitable"
{| class="wikitable"
! Name !! Nachname
! Salonname !! Nachname
|-
|-
| Friedrich List Frisuren || Krause
| Friedrich List Frisuren || Krause
Zeile 142: Zeile 154:
|}
|}


=== Right Join (Inklusive rechter Tabelle) ===
=== Rechter äußerer Verbund (RIGHT JOIN) ===
Alle Einträge der rechten Tabelle (Tab. B) werden selektiert, auch wenn keine Verbindung zur linken besteht.
<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>


<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
SELECT Salon.Name, Mitarbeiter.Nachname
-- Hier: Alle Salons (Rechts) anzeigen, auch wenn keine Mitarbeiter (Links) zugeordnet sind
FROM Salon RIGHT JOIN Mitarbeiter ON Salon.IdSalon = Mitarbeiter.FKSalon;
SELECT Mitarbeiter.Nachname, Salon.Name AS Salonname
FROM Mitarbeiter  
RIGHT JOIN Salon ON Mitarbeiter.FKSalon = Salon.IdSalon;
</syntaxhighlight>
</syntaxhighlight>
'''Ergebnis:'''
{| class="wikitable"
! Nachname !! Salonname
|-
| Krause || Friedrich List Frisuren
|-
| Schrotter || Friedrich List Frisuren
|-
| Hermann || Friedrich List Frisuren
|-
| Krause || Hammer Haare
|-
| Bitter || Hammer Haare
|-
| ''NULL'' || Kaiserschnitt
|}


== Gruppierung und Aggregate ==
== Gruppierung und Aggregat-Funktionen ==
Mit '''GROUP BY''' werden Datensätze aggregiert (z. B. `COUNT`, `SUM`, `AVG`). Möchte man die Datensätze in einer gruppierten Abfrage filtern, muss '''HAVING''' anstatt `WHERE` verwendet werden.


<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
SELECT SUM(Rechnungsbetrag) AS Umsatz, Mitarbeiter.Nachname  
SELECT SUM(Termin.Rechnungsbetrag) AS Umsatz, Mitarbeiter.Nachname AS Mitarbeiter
FROM Termin
FROM TERMIN
INNER JOIN Mitarbeiter ON Termin.FKMitarbeiter = Mitarbeiter.IdMitarbeiter  
INNER JOIN Mitarbeiter ON Termin.FKMitarbeiter = Mitarbeiter.IdMitarbeiter  
GROUP BY Mitarbeiter.IdMitarbeiter  
GROUP BY Mitarbeiter.IdMitarbeiter  
Zeile 172: Zeile 204:
| 106 || Schrotter
| 106 || Schrotter
|}
|}
''(Berechnung: Claudia Schrotter [ID 2] hatte Termine über 29 und 77 Euro.)''
 
== Unterabfragen (Verschachtelt) ==
Unterabfragen werden in Klammern gesetzt und liefern Werte für die Hauptabfrage.
<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. Die Spalten müssen vom gleichen Typ sein.
<syntaxhighlight lang="sql">
SELECT Mitarbeiter.nachname FROM Mitarbeiter
UNION
SELECT Kunde.nachname FROM Kunde;
</syntaxhighlight>
 
== Reihenfolge der Abarbeitung ==
Das DBMS arbeitet eine DQL-Abfrage logisch in dieser Reihenfolge ab:
# '''FROM''' (inkl. JOINs)
# '''WHERE'''
# '''GROUP BY'''
# '''HAVING'''
# '''SELECT'''
# '''ORDER BY'''
# '''LIMIT'''


[[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