DQL: Unterschied zwischen den Versionen
Die Seite wurde neu angelegt: „Die '''Data Query Language (DQL)''' ist der Teilbereich von SQL, der zur Abfrage und Zusammenstellung von Informationen aus Datenbanktabellen dient. Das Ergebnis einer DQL-Abfrage ist eine Relation, die in der Regel als temporäre Tabelle dargestellt wird. DQL-Abfragen basieren auf den Operationen der '''relationalen Algebra''' (Selektion, Projektion, Join etc.). == Datenbasis & Modellierung == Um komplexe Abfragen zu verstehen, ist die Kenntnis…“ |
Keine Bearbeitungszusammenfassung |
||
| (5 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
| Zeile 1: | Zeile 1: | ||
Die '''Data Query Language (DQL | == 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 == | |||
[[Datei:DQLDatenbasisERM.jpg|mini|ERM-Modell zur Datenbasis]] | |||
[[Datei:DQLDatenbasisTabellen.jpg|mini|Tabellenübersicht]] | |||
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`. | |||
== | == 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. | |||
<syntaxhighlight lang="sql"> | |||
SELECT Nachname AS Mitarbeitername, IdMitarbeiter 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 mit Spaltenauswahl:''' | |||
<syntaxhighlight lang="sql"> | <syntaxhighlight lang="sql"> | ||
SELECT nachname, vorname FROM Mitarbeiter; | |||
SELECT | |||
FROM Mitarbeiter; | |||
</syntaxhighlight> | </syntaxhighlight> | ||
= | '''Ergebnis:''' | ||
{| class="wikitable" | |||
! nachname !! vorname | |||
|- | |||
| Krause || Sabine | |||
|- | |||
| Schrotter || Claudia | |||
|- | |||
| Hermann || Markus | |||
|- | |||
| Krause || Christoph | |||
|- | |||
| Bitter || Manuel | |||
|} | |||
- | == 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. | |||
== | '''Beispiel komplexer Filter:''' | ||
<syntaxhighlight lang="sql"> | |||
SELECT Vorname, Nachname FROM Mitarbeiter | |||
WHERE (Nachname = 'Krause' OR Vorname = 'Manuel') AND IdMitarbeiter <> 1; | |||
</syntaxhighlight> | |||
'''Ergebnis:''' | |||
{| class="wikitable" | |||
! Vorname !! Nachname | |||
|- | |||
| Christoph || Krause | |||
|- | |||
| Manuel || Bitter | |||
|} | |||
=== 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"> | <syntaxhighlight lang="sql"> | ||
SELECT * FROM Termin WHERE Datum IS NOT NULL; | |||
SELECT * FROM Termin | |||
WHERE | |||
</syntaxhighlight> | </syntaxhighlight> | ||
=== ORDER BY | == Sortierung und Begrenzung == | ||
* ''' | === ORDER BY === | ||
Mit '''ORDER BY''' wird die Sortierreihenfolge festgelegt. | |||
* '''ASC:''' aufsteigend (Standard) | |||
* '''DESC:''' absteigend | |||
<syntaxhighlight lang="sql"> | <syntaxhighlight lang="sql"> | ||
SELECT | SELECT Nachname, Vorname FROM Mitarbeiter ORDER BY Nachname ASC; | ||
ORDER BY | |||
</syntaxhighlight> | </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"> | |||
SELECT * FROM Warenkorbposition ORDER BY Datum DESC LIMIT 10; | |||
</syntaxhighlight> | |||
== Tabellen verknüpfen (JOINs) == | == Tabellen verknüpfen (JOINs) == | ||
Werden Informationen unterschiedlicher Tabellen zusammengefügt, müssen diese über Schlüsselfelder verbunden werden. | |||
=== Innerer natürlicher Verbund (INNER JOIN) === | |||
Zeigt nur Datensätze an, für die in beiden Tabellen eine Entsprechung existiert. | |||
<html> | |||
<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="130" cy="60" r="50" stroke="black" stroke-width="2" fill="white" /> | |||
<clipPath id="inner"> | |||
<circle cx="70" cy="60" r="50" /> | |||
</clipPath> | |||
<circle cx="130" cy="60" r="50" fill="#3498db" clip-path="url(#inner)" /> | |||
<text x="45" y="65" font-size="12">Tab. A</text> | |||
<text x="135" y="65" font-size="12">Tab. B</text> | |||
</svg> | |||
</html> | |||
<syntaxhighlight lang="sql"> | <syntaxhighlight lang="sql"> | ||
SELECT Salon.Name, Mitarbeiter.Nachname | SELECT Salon.IdSalon, Salon.Name AS Salonname, Mitarbeiter.Nachname | ||
FROM Salon | FROM Salon | ||
INNER JOIN Mitarbeiter ON Salon.IdSalon = Mitarbeiter.FKSalon; | INNER JOIN Mitarbeiter ON Salon.IdSalon = Mitarbeiter.FKSalon; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Ergebnis:''' (Salon 3 "Kaiserschnitt" erscheint nicht, da ihm kein Mitarbeiter zugeordnet ist) | |||
{| class="wikitable" | |||
! IdSalon !! Salonname !! Nachname | |||
|- | |||
| 1 || Friedrich List Frisuren || Krause | |||
|- | |||
| 1 || Friedrich List Frisuren || Schrotter | |||
|- | |||
| 1 || Friedrich List Frisuren || Hermann | |||
|- | |||
| 2 || Hammer Haare || Krause | |||
|- | |||
| 2 || Hammer Haare || Bitter | |||
|} | |||
=== LEFT | === 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> | |||
<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="70" cy="60" r="50" stroke="black" stroke-width="2" fill="#3498db" /> | |||
<text x="45" y="65" font-size="12">Tab. A</text> | |||
<text x="135" y="65" font-size="12">Tab. B</text> | |||
</svg> | |||
</html> | |||
--- | <syntaxhighlight lang="sql"> | ||
SELECT Salon.Name AS Salonname, Mitarbeiter.Nachname | |||
FROM Salon | |||
LEFT JOIN Mitarbeiter ON Salon.IdSalon = Mitarbeiter.FKSalon; | |||
</syntaxhighlight> | |||
'''Ergebnis:''' | |||
{| class="wikitable" | |||
! Salonname !! Nachname | |||
|- | |||
| Friedrich List Frisuren || Krause | |||
|- | |||
| Friedrich List Frisuren || Schrotter | |||
|- | |||
| Friedrich List Frisuren || Hermann | |||
|- | |||
| Hammer Haare || Krause | |||
|- | |||
| Hammer Haare || Bitter | |||
|- | |||
| Kaiserschnitt || ''NULL'' | |||
|} | |||
== | === Rechter äußerer Verbund (RIGHT JOIN) === | ||
Alle Einträge der rechten Tabelle (Tab. B) werden selektiert, auch wenn keine Verbindung zur linken besteht. | |||
<html> | |||
<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="130" cy="60" r="50" stroke="black" stroke-width="2" fill="#3498db" /> | |||
<text x="45" y="65" font-size="12">Tab. A</text> | |||
<text x="135" y="65" font-size="12">Tab. B</text> | |||
</svg> | |||
</html> | |||
<syntaxhighlight lang="sql"> | |||
-- Hier: Alle Salons (Rechts) anzeigen, auch wenn keine Mitarbeiter (Links) zugeordnet sind | |||
SELECT Mitarbeiter.Nachname, Salon.Name AS Salonname | |||
FROM Mitarbeiter | |||
RIGHT JOIN Salon ON Mitarbeiter.FKSalon = Salon.IdSalon; | |||
</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 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 | SELECT SUM(Termin.Rechnungsbetrag) AS Umsatz, Mitarbeiter.Nachname AS Mitarbeiter | ||
FROM | FROM TERMIN | ||
INNER JOIN Termin | INNER JOIN Mitarbeiter ON Termin.FKMitarbeiter = Mitarbeiter.IdMitarbeiter | ||
GROUP BY Mitarbeiter. | GROUP BY Mitarbeiter.IdMitarbeiter | ||
HAVING Umsatz > 100; | HAVING Umsatz > 100; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Ergebnis:''' | |||
{| class="wikitable" | |||
! Umsatz !! Mitarbeiter | |||
|- | |||
| 106 || Schrotter | |||
|} | |||
== Unterabfragen (Verschachtelt) == | |||
Unterabfragen werden in Klammern gesetzt und liefern Werte für die Hauptabfrage. | |||
<syntaxhighlight lang="sql"> | <syntaxhighlight lang="sql"> | ||
-- Termine | -- Termine mit unterdurchschnittlichem Umsatz | ||
SELECT TerminID, Rechnungsbetrag | SELECT TerminID, Rechnungsbetrag FROM Termin | ||
FROM Termin | |||
WHERE Rechnungsbetrag < (SELECT AVG(Rechnungsbetrag) FROM Termin); | WHERE Rechnungsbetrag < (SELECT AVG(Rechnungsbetrag) FROM Termin); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== UNION == | |||
Mit '''UNION''' werden zwei Relationen vereint. Die Spalten müssen vom gleichen Typ sein. | |||
<syntaxhighlight lang="sql"> | <syntaxhighlight lang="sql"> | ||
SELECT nachname FROM Mitarbeiter | SELECT Mitarbeiter.nachname FROM Mitarbeiter | ||
UNION | UNION | ||
SELECT nachname FROM Kunde; | SELECT Kunde.nachname FROM Kunde; | ||
</syntaxhighlight> | </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]] | ||