Chapter 8. Database Queries

TO BE TRANSLATED...

Ein DBMS muss es ermöglichen, die in einer DB gespeicherten Informationen bei Bedarf wieder abzurufen. Dazu werden normalerweise DB-Anfragen formuliert, die ausdrücken, um welche Informationen es geht. In einem RDBMS geht es um Werte für bestimmte Attribute in bestimmten Tabellenzeilen. Diese Werte bilden die Antworten (bzw. die Antwortmenge), die das RDBMS bei der Verarbeitung einer Anfrage erzeugt. Da eine Antwort die Form eines Werte-Tupels hat, entspricht die erzeugte Antwortmenge einer Tabelle.

Um diesen Sachverhalt zu illustrieren, betrachten wir folgende RDB:

books
isbntitleyearpublisher
006251587XWeaving the Web2000Harper Business
0465026567Gödel, Escher, Bach1999Basic Books
0465030793I Am A Strange Loop2000Basic Books
0321312562Database Systems2005Pearson International
publishers
nameaddress
Basic BooksNew York, USA
Pearson InternationalLondon, Great Britain
Harper BusinessNew York, USA

Wenn nach Buchtitel, Verlag und Verlagsadresse aller erfassten Bücher, die im Jahr 2000 erschienen sind, gefragt wird, ergibt sich folgende Antwort-Tabelle:

query results
titlepublisheraddress
I Am A Strange LoopBasic BooksNew York, USA
Weaving the WebHarper BusinessNew York, USA

Diese Anfrage entspricht folgender SQL-Abfrage:

1
2
3
SELECT title, publisher, address
FROM books, publishers
WHERE year = 2000 AND publisher = name

Diese Abfrage besteht aus drei Schritten:

  1. sie bildet eine Produktverknüpfung der beiden Tabellen books und publishers in der FROM-Klausel,
  2. sie selektiert dann durch die WHERE-Klausel diejenigen Zeilen, die die Spaltengleichheitsbedingung publisher = name sowie die Spaltenwertbedingung year = 2000 erfüllen, und
  3. projiziert schließlich durch die SELECT-Klausel die selektierten Zeilen auf die drei Attribute title, publisher, address.

Die Abfrage wird also mit Hilfe der drei Tabellen-Operationen Produkt, Selektion und Projektion ausgewertet.

Wenn man eine SQL-Abfrage in MS Access eingibt und sie auswerten lässt, kann es sein, dass die Abfrage automatisch umgeschrieben wird. Insbesondere werden Attributnamen um Tabellennamen erweitert (wie z.B. "books.title" statt "title" ) und von Access reservierte Wörter (wie z.B. "Name") werden in eckigen Klammern gesetzt.

Einfache Abfragen

Eine einfache Abfrage setzt sich aus den drei SQL-Klauseln SELECT, FROM und WHERE zusammen, wobei sich die FROM-Klausel nur auf eine Tabelle bezieht, mit SELECT eine Projektion auf eine Teilmenge der Attribute (bzw. Spalten) und mit WHERE eine Selektion der resultierenden Zeilen mit Hilfe von einfachen Zeilenbedingungen vorgenommen wird.

Die allereinfachste Abfrage fragt nach dem Inhalt einer Tabelle, wie z.B.

Beispiel 8-1. Welche Informationen gibt es über Bücher?
SELECT * FROM books
query results
isbntitleyearpublisher
006251587XWeaving the Web2000Harper Business
0465026567Gödel, Escher, Bach1999Basic Books
0465030793I Am A Strange Loop2000Basic Books
0321312562Database Systems2005Pearson International

Hierbei werden in der SELECT-Klausel mit dem Wildcard-Symbol * alle Attribute berücksichtigt. Eine Projektion, also eine Einschränkung auf bestimmte Attribute, wird vermieden. Um das Abfrageresultat auf eine relevante Teilmenge der Attribute einzuschränken, muss in der SELECT-Klausel durch Aufzählung der interessierenden Attribute eine entsprechende Projektion vorgenommen werden, wie z.B. in folgender Abfrage:

Beispiel 8-2. Erstelle eine Liste aller Bücher mit ISBN und Titel
SELECT isbn, title FROM books
query results
isbntitle
006251587XWeaving the Web
0465026567Gödel, Escher, Bach
0465030793I Am A Strange Loop
0321312562Database Systems

Symbolisch kann eine Projektion einer der Tabelle books auf eine Teilmenge [isbn, title] ihrer Spalten folgendermaßen notiert werden:

Proj( [isbn, title], books)

Um nach bestimmten Büchern zu suchen, muss eine Selektionsbedingung in einer WHERE-Klausel angegeben werden, wie z.B.

Beispiel 8-3. Erstelle eine Liste aller Bücher (mit ISBN und Titel), die im Jahr 2000 erschienen sind
SELECT isbn, title 
FROM books
WHERE year = 2000
query results
isbntitle
006251587XWeaving the Web
0465030793I Am A Strange Loop

Elementare Selektionsbedingungen können nicht nur mit dem Gleicheitsprädikat, sondern auch mit anderen Vergleichsprädikaten (<, >, !=, etc.) sowie mit dem Intervall-Prädikat BETWEEN und dem String-Muster-Prädikat LIKE gebildet werden. Z.B. verlangt die Bedingung price BETWEEN 10 AND 20, dass der Wert des Attributs price zwischen 10 und 20 (inklusive) liegt. Die Bedingung title LIKE '%and%' verlangt, dass der Wert des Attributs title den Teilstring 'and' enthält. Dabei ist '%' ein Wildcard-Symbol für irgendeinen String (in MS Access wird anstatt dem Symbol '%' das gängugere Wildcard-Symbol '*'.sowie '?' anstatt '_' für ein einzelnes beliebiges Zeichen verwendet).

Symbolisch kann eine Selektion der Tabelle books mit einer Selektionsbedingung year=2000 folgendermaßen notiert werden:

Sel( year = 2000, books)

Die Kombination einer Projektion und einer Selektion kann folgendermaßen notiert werden:

Proj( [isbn, title], Sel( year = 2000, books))

Die Zeilen einer Ergebnistabelle können mit einer ORDER-BY-Klausel sortiert werden, wie im nächsten Abfragebeispiel gezeigt wird.

Beispiel 8-4. Erstelle eine nach Titel geordnete Liste aller Bücher (mit ISBN und Titel), die im Jahr 2000 erschienen sind
SELECT isbn, title 
FROM books 
WHERE year = 2000
ORDER BY title
query results
isbntitle
0465030793I Am A Strange Loop
006251587XWeaving the Web

Wenn die Sortierung in absteigender Reihenfolge erfolgen soll, ist das Schlüsselwort DESC an die ORDER-BY-Klausel anzuhängen, wie in ORDER BY title DESC.

Statistische Abfragen

Wir erweitern die oben präsentierte Tabelle books durch Hinzufügung einer Spalte price für den Buchpreis:

books
isbntitleyearpricepublisher
006251587XWeaving the Web200016.00Harper Business
0465026567Gödel, Escher, Bach199917.99Basic Books
0465030793I Am A Strange Loop200014.99Basic Books
0321312562Database Systems200560.00Pearson International

Immer wenn wir derartige Daten haben, kann es sein, dass wir gewisse Statistiken aus ihnen gewinnen wollen:

  1. Wie viele Bücher gibt es pro Verlag?
  2. Was ist das Erscheinungsjahr des ältesten Buchs in der Datenbank?
  3. Was ist der Durchschnittspreis der Bücher des Verlags Basic Books?

Diese drei Beispiele statistischer Anfragen werden in den folgenden SQL-Abfragen ausgedrückt.

Beispiel 8-5. Statistische Anfrage 1: Wieviele Bücher gibt es pro Verlag?
SELECT publisher, COUNT(*) AS nmr_of_books 
FROM books
GROUP BY publisher
query results
publishernmr_of_books
Harper Business1
Basic Books2
Pearson International1

Bei dieser Abfrage werden drei noch nicht behandelte SQL-Elemente verwendet:

  1. Die COUNT-Aggregatfunktion mit dem Wildcard-Symbol * als Argument bestimmt die Anzahl von Zeilen. Da in dieser Abfrage die Ergebnistabelle gruppiert ist, wird die Zeilenanzahl pro Gruppe ermittelt. Wenn als Argument ein Attribut angegeben ist, wird die Anzahl von Zeilen mit einem Wert für das Attribut (genauer gesagt, mit einem von NULL verschiedenen Attributwert) ermittelt.
  2. Mit Hilfe von AS kann ein Attribut in der Ergebnistabelle mit einem anderen Spaltentitel ausgegeben oder ein Spaltentitel für einen berechneten Ausdruck definiert werden.
  3. Die GROUP-BY-Klausel erlaubt es, Zeilen in der Ergebnistabelle nach einem (oder mehreren) Attribut(en) zu gruppieren und für eine Gruppe nur eine Ergebniszeile zu erzeugen. In der SELECT-Klausel einer GROUP-BY-Abfrage können außer Berechnungsausdrücken nur solche Attribute angegeben werden, die auch in der GROUP-BY-Klausel angegeben sind.

Um das Erscheinungsjahr des ältesten Buchs zu ermitteln, kann nach der minimalen Jahreszahl mit Hilfe der Aggregatfunktion MIN gesucht werden:

Beispiel 8-6. Statistische Anfrage 2: Was ist das Erscheinungsjahr des ältesten Buchs in der Datenbank?
SELECT MIN(year) AS earliest_year
FROM books
query results
earliest_year
1999

Außer COUNT und MIN gibt es noch folgende Aggregatfunktionen: MAX für maximale Werte, AVG für Durchschnittswerte und SUM für Summenbildung. Beispielsweise kann die Frage "was ist der Durchschnittspreis der Bücher des Verlags Basic Books?" folgendermaßen ausgedrückt werden:

Beispiel 8-7. Statistische Anfrage 3: Was ist der Durchschnittspreis der Bücher des Verlags Basic Books?
SELECT AVG(price) AS average_price_of_Basic_Books
FROM books
WHERE publisher = 'Basic Books'
query results
average_price_of_Basic_Books
16,49

Verschachtelte Abfragen

Eine Abfrage kann anstelle von bestimmten Werten oder Tabellen auch Unterabfragen enthalten, die einen zu berechnenden Wert bzw. eine zu berechnende Tabelle repräsentieren.

Eine Variante der obigen Abfrage nach den Häufigkeiten von publzierten Büchern pro Verlag ergibt sich, wenn die durch COUNT(publisher) ausgedrückte absolute Häufigkeit durch eine relative Häufigkeit ersetzt wird. Dazu ist die absolute Häufigkeit durch die per SELECT COUNT(*) FROM books ermittelte Gesamtzahl der Tabellenzeilen zu dividieren. Es wird also ein zu berechnender Wert in einem Spaltenwertausdruck durch eine Unterabfrage ermittelt bzw. repräsentiert., wie in folgendem Beispiel gezeigt wird

Beispiel 8-8. Welchen prozentualen Bücher-Anteil hat jeder Verlag?
SELECT publisher, 
  COUNT(publisher) / (SELECT COUNT(*) FROM books) AS perc_of_books 
FROM books
GROUP BY publisher
query results
publisherperc_of_books
Harper Business0.25
Basic Books0.5
Pearson International0.25

Eine Unterabfrage kann auch in der durch die WHERE-Klausel ausgedrückten Selektionsbedingung vorkommen. Z.B. könnte von den selektierten Zeilen mit Hilfe einer IN-Bedingung verlangt werden, dass ihre Werte für ein Attribut a1 in einer durch eine Unterabfrage berechneten Wertemenge vorkommt:

SELECT * FROM table1
WHERE a1 IN (SELECT a2 FROM table2 WHERE cond2)

Oder es könnte verlangt werden, dass der Wert von a1 kleiner als alle Werte einer Unterabfrage ist, was mit Hilfe von ALL geprüft werden kann:

SELECT * FROM table1
WHERE a1 < ALL (SELECT a2 FROM table2 WHERE cond2)

Auf ähnliche Weise kann mit ANY statt ALL geprüft werden, ob ein Wert kleiner als irgendein Wert einer Unterabfrage ist. Schließlich kann mit Hilfe von EXISTS geprüft werden, ob eine Unterabfrage ein nicht-leeres Resultat hat, es also wenigstens einen Wert bzw. eine Zeile im Resultat gibt.

Abfragen mit mehreren Tabellen

Der Informationsbestand einer Datenbank ist über eine Menge von Tabellen aufgeteilt. Immer wenn bei einer Abfrage Informationen aus mehr als einer Tabelle benötigt werden, müssen diese Tabellen in der Abfrage miteinander verbunden werden. Es gibt verschiedene Tabellen-Verbindungsoperationen. Die wichtigste heißt innerer Verbund (engl. inner join). Alle Verbund-Operationen basieren auf dem Kartesischen Produkt zweier Tabellen, T1 × T2, das wie in der Mengenlehre als Menge aller möglichen Kombinationen definiert ist.

Um ein überschaubares Beispiel für ein Kartesisches Produkt zu erhalten, betrachten wir folgende vereinfachte Bibliotheksdatenbank:

books
isbntitlepublisher
006251587XWeaving the WebHarper Business
0465026567Gödel, Escher, BachBasic Books
publishers
nameaddress
Basic BooksNew York, USA
Pearson InternationalLondon, Great Britain
Harper BusinessNew York, USA

Für diese beiden Tabellen erhalten wir folgendes Kartesische Produkt:

books × publishers
isbntitlepublishernameaddress
006251587XWeaving the WebHarper BusinessBasic BooksNew York, USA
006251587XWeaving the WebHarper BusinessPearson InternationalLondon, Great Britain
006251587XWeaving the WebHarper BusinessHarper BusinessNew York, USA
0465026567Gödel, Escher, BachBasic BooksBasic BooksNew York, USA
0465026567Gödel, Escher, BachBasic BooksPearson InternationalLondon, Great Britain
0465026567Gödel, Escher, BachBasic BooksHarper BusinessNew York, USA

Dies entspricht folgender SQL-Abfrage:

SELECT * FROM books, publishers

Ein innerer Verbund zweier Tabellen T1 und T2 mit Verbundbedingung C ist eine Selektion des Kartesischen Produkts T1 × T2. Symbolisch:

T1C T2 = Sel( C, T1 × T2)

Ein Beispiel ist der innere Verbund

bookspublisher=name publishers,

der es erlaubt, Informationen aus beiden Tabellen (den Buchtitel, den Verlag und seine Adresse) pro Buch wie in Beispiel 8-9 zusammenzuführen.

Beispiel 8-9. Erstelle eine Liste aller erfassten Bücher mit Buchtitel, Verlag und Verlagsadresse
SELECT title, publisher, address
FROM books INNER JOIN publishers ON books.publisher = publishers.name
query results
titlepublisheraddress
Weaving the WebHarper BusinessNew York, USA
Gödel, Escher, BachBasic BooksNew York, USA

Alternativ kann eine solche Verbundabfrage auch ohne die Verbundbildung in der FROM-Klausel als Kombination aus Selektion (in der WHERE-Klausel) und Kartesischem Produkt (in der FROM-Klausel) formuliert werden:

SELECT title, publisher, address
FROM books, publishers
WHERE books.publisher = publishers.name

Wenn man in MS Access Beziehungen zwischen den in einer Abfrage beteiligten Tabellen definiert hat, werden entsprechende Verbund-Abfragen auf der Basis dieser Beziehungen vorgeschlagen.

Vereinigung und Differenz

Während die Verbund-Operation zur Auswertung einer konjunktiven (AND) Anfrage dient, werden zur Auswertung von disjunktiven (OR) bzw. konjunktiv-negierten (AND-NOT) Anfragen die Tabellenoperationen Vereinigung (UNION) und Differenz (EXCEPT) verwendet.

Wir betrachten folgendes DB-Schema:

people = ⟨ id, name⟩

movies = ⟨ id, title, release_date, director⟩

people_as_actors_in_movies = ⟨ person_id, movie_id⟩

Zu diesem Schema können wir folgende Abfragen definieren:

Beispiel 8-10. Erstelle eine Liste (von Personenkennzeichen) aller Schauspieler und Regisseure
SELECT director FROM movies UNION 
   SELECT person_id FROM people_as_actors_in_movies
Beispiel 8-11. Welche Regisseure sind keine Schauspieler?
SELECT director FROM movies EXCEPT 
   SELECT person_id FROM people_as_actors_in_movies