DQL: Unterschied zwischen den Versionen

Aus FLBK-Wiki
Zur Navigation springen Zur Suche springen
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]]

Version vom 26. Februar 2026, 14:24 Uhr

Einführung

Die Data Query Language (kurz DQL) der 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

ERM-Modell zur Datenbasis
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.

SELECT IdMitarbeiter AS Mitarbeiternr, Nachname FROM Mitarbeiter;

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:

SELECT * FROM Mitarbeiter;

Ergebnis:

IdMitarbeiter Nachname Vorname FkSalon
1 Krause Sabine 1
2 Schrotter Claudia 1
3 Hermann Markus 1
4 Krause Christoph 2
5 Bitter Manuel 2

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:

SELECT Vorname, Nachname FROM Mitarbeiter 
WHERE (Nachname = 'Krause' OR Vorname = 'Manuel') AND IdMitarbeiter <> 1;

Ergebnis:

Vorname Nachname
Christoph Krause
Manuel Bitter

IS NULL

SQL nutzt NULL-Werte für fehlende Daten. Die Prüfung erfolgt mit `IS NULL` oder `IS NOT NULL`.

SELECT * FROM Termin WHERE Datum IS NOT NULL;

Sortierung und Begrenzung

ORDER BY

Mit ORDER BY wird die Sortierreihenfolge festgelegt.

  • ASC: aufsteigend (Standard)
  • DESC: absteigend
SELECT Nachname, Vorname FROM Mitarbeiter ORDER BY Nachname ASC;

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.

SELECT * FROM Warenkorbposition ORDER BY Datum DESC LIMIT 10;

Tabellen verknüpfen (JOINs)

Werden Informationen aus unterschiedlichen Tabellen benötigt, müssen diese verbunden werden.

Innerer natürlicher Verbund (INNER JOIN)

Zeigt nur Datensätze an, für die in beiden Tabellen eine Entsprechung existiert. Tab. A Tab. B

SELECT Salon.Name AS Salonname, Mitarbeiter.Nachname 
FROM Salon INNER JOIN Mitarbeiter ON Salon.IdSalon = Mitarbeiter.FKSalon;

Linker äußerer Verbund (LEFT JOIN)

Alle Datensätze der linken Tabelle werden angezeigt, die der rechten nur bei Übereinstimmung. Tab. A Tab. B

Rechter äußerer Verbund (RIGHT JOIN)

Alle Einträge der rechten Tabelle werden selektiert, auch ohne Verbindung zur linken. Tab. A Tab. B

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).
SELECT SUM(Rechnungsbetrag) AS Umsatz, Mitarbeiter.Nachname 
FROM Termin INNER JOIN Mitarbeiter ON Termin.FKMitarbeiter = Mitarbeiter.IdMitarbeiter 
GROUP BY Mitarbeiter.IdMitarbeiter HAVING Umsatz > 100;

Ergebnis: 106 | Schrotter (Da Claudia Schrotter Termine über 29€ und 77€ hatte).

Unterabfragen (Verschachtelt)

Unterabfragen liefern Informationen, die als Grundlage für die Hauptabfrage dienen. Sie müssen immer in Klammern gesetzt werden.

-- Termine mit unterdurchschnittlichem Umsatz
SELECT TerminID, Rechnungsbetrag FROM Termin 
WHERE Rechnungsbetrag < (SELECT AVG(Rechnungsbetrag) FROM Termin);

UNION

Mit UNION werden zwei Relationen vereint. Doppelte Werte werden ignoriert. Die Spalten müssen vom gleichen Typ sein.

SELECT nachname FROM Mitarbeiter UNION SELECT nachname FROM Kunde;

Reihenfolge der Abarbeitung

Das DBMS arbeitet eine DQL-Abfrage logisch von "innen nach außen" in dieser Reihenfolge ab:

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.
7 LIMIT Auswahl der relevanten Datensatzzahl.