Grundkonstruktion einer SQL-Abfrage ist von der Form
„SELECT attributListe FROM relation“
SELECT name,adresse FROM restaurant;
entspricht
$ π_{name,adresse}(restaurant) $
SELECT * FROM restaurant; /*liefert die gesamte Tabelle (d.h. mit allen Attributen)
SQL-Abfrage mit Verknüpfung mehrerer Relationen:
„SELECT attributListe FROM relationen WHERE bedingung“
Eine solche SQL-Abfrage wird ausgewertet, indem zunächst das kartesische Produkt der in der FROM-Klausel angegebenen Relationen gebildet wird. Daraus werden dann jene Tupel ausgewählt, die die in der WHERE-Klausel angegebenen Bedingungen erfüllen. Zudem wird auf die in der SELECT-Klausel angegebenen Attribute dieser Tupel projiziert.
Wir wollen wissen welche Speisen in welchem Restaurant angeboten werden.
SELECT * FROM Speise, Restaurant WHERE Restaurant.rnr = Speise.rnr;
Die Bedingunng in der WHERE-Klausel kann sich aus mehreren, durch die logischen Operatoren AND, OR und NOT verbundenen Teilbedingungen zusammensetzen.
SELECT rnr, name, haube, typ FROM restaurant WHERE haube > 1 AND NOT (typ='österreichisch' OR typ='international');
In der SELECT-Klausel können auch Ausdrücke, die aus Attributen berechnet werden, stehen. Durch das Schlüsselwort AS kann einem so berechneten Ausdruck ein Attributname zugewiesen werden.
Wir wollen alle Paare von Restaurants auswählen, die sich um mehr als zwei Hauben unterscheiden und die Differenz der Hauben ausgeben.
SELECT r1.name, r2.name, (r2.haube-r1.haube) AS differenz FROM restaurant r1, restaurant r2 WHERE r1.haube +2 < r2.haube;
In SQL werden Duplikate, d.h. Ergebnistupel mit identischen Werten, nicht automatisch eliminiert. Um Duplikate zu eliminieren, muss der Liste von ausgewählten Attribute das Schlüsselwort DISTINCT vorangestellt werden.
Durch die Angabe einer ORDER BY-Klausel mit den Schlüsselworten ASC oder DESC kann die Ausgabe aufsteigend bzw. absteigend nach bestimmten Attributen sortiert werden. Der Defaultwert ist ASC.
Wir wollen eine alphabetisch sortierte Liste aller Speisen von Restaurants mit mehr als einer Haube.
SELECT DISTINCT s.name FROM Restaurant r, Speise r WHERE (r.rnr = s.rnr) AND (r.haube>1) ORDER BY s.name, s.preis;
Gegeben sind folgende Relationen
Person (id, name, plz)
Orte (plz, ort)
Mitarbeiter (id, gehalt, abtnr)
Kunde (id, rabatt)
Abteilung (abtnr, name)
PKW (marke, ps, id, fahrgestellnr)
Entwickeln Sie SQL-Anweisungen für folgende Abfragen
1) SELECT name FROM Person p, Orte o WHERE o.ort="Amstetten" AND p.plz=o=plz; 2) SELECT name FROM Person p, Orte o, Mitarbeiter m WHERE m.id=p.id AND o.ort="Amstetten" AND p.plz=o.plz; 3) SELECT name FROM Person p, Orte o, Mitarbeiter m WHERE m.id=p.id AND m.id=k.id; 4) SELECT name FROM Person p, Mitarbeiter m, PKW WHERE p.id=m.id AND PKW.id=p.id AND PKW.ps>100; 5) SELECT ort FROM Orte o, Mitarbeiter m, Person p, Abteilung a WHERE o.plz=p.plz AND p.id=m.id AND m.abtnr=a.abtnr AND p.plz=o.plz;
Neben den Boolschen Funktionen (AND,OR,NOT) sind folgende weitere Angaben zulässig:
Anstatt eine Reihe von OR-Verknüpfungen durchzuführen, kann auch der IN-Operator verwendet werden.
Bsp:
SELECT * FROM ... WHERE typ IN ('österreichisch', 'international');
Bsp.:
SELECT * FROM ... WHERE preis BETWEEN 100 AND 150; //ist dasselbe wie SELECT * FROM ... WHERE preis >= 100 AND preis<=150;
Bsp.: Es sollen alle Personen gesucht werden, die beim Attribut TelNr den NULL-Wert eingetragen haben.
SELECT * FROM ... WHERE TelNr IS NULL;
Der Like-Operator ist ein Vergleichsoperator, der Datenwerte einer Spalte mit einem vorgegebenen Muster vergleicht.
Allgemeine Form:
AttributName [NOT] LIKE 'muster';
Dabei haben in 'muster' zwei Zeichen eine besondere Bedeutung:
Bsp.: Alle Speisen deren Name mit 'M' beginnt
SELECT Name FROM Speise WHERE Name LIKE 'M%';
Bsp.: Alle Restaurants, welche an 2. Stelle im Namen ein 'o' haben
SELECT Name FROM Restaurant WHERE Name LIKE '_o%';
SQL stellt die Mengenoperationen UNION (Vereinigung), INTERSECT (Durchschnitt) und EXCEPT (Mengendifferenz) für typkompatible Relationen (d.h. Relationen mit der gleichen Anzahl von jeweils typkompatiblen Attributen) zur Verfügung.
Beispiel: Wir wollen eine Liste der Namen aller Restaurants und der Namen aller Speisen
(SELECT Name FROM Restaurant) UNION (SELECT Name FROM Speise) oder SELECT Name FROM Restaurant WHERE Name NOT IN (SELECT Name FROM Speise)
Mit typkompatiblen Relationen sind dabei nicht die Relationen Restaurant oder Speise gemeint, sondern die Ergebnisse der beiden SELECT Statements.
Es gibt folgende Aggregatfunktionen in SQL:
Bsp: Gesucht ist der Preis des teuersten Burgers:
SELECT MAX(Preis) FROM Speise WHERE Name LIKE '%Burger%';
Bsp.: Wie viele Speisen werden im Brauhof angeboten?
SELECT COUNT(*) //COUNT(*) zählt alle Tupel FROM Restaurant r, Speise s, WHERE r.rnr = s.rnr AND r.name="Brauhof";
Die Select-Abfrage kann um eine Klause „GROUP BY attributListe“ und eine Klausel „HAVING bedingung“ ergänzt werden, um Gruppen von Tupeln zu bilden und auf diese Gruppen Aggregatfunktionen anzuwenden.
Dabei werden diese Tupel nach gemeinsamen Werten in den in der GROUP BY-Klausel angeführten Attributen gruppiert. Von diesen Gruppen werden jene eliminiert, die die in der HAVING-Klausel angegebene Bedingung nicht erfüllen.
Anschließend werden etwaige in der SELECT-Klausel angegebenen Aggregatfunktionen auf jede der verbliebenen Gruppen angewendet. Diese Aggregatfunktionen (außer COUNT) können auch auf arithmetische Ausdrücke über Attributen angewandt werden.
| Relation Restaurant | |||
|---|---|---|---|
| rnr | RName | Adr | Haube |
| 1 | McDonalds | Amstetten | 0 |
| 2 | McDonalds | Ybbs | 0 |
| 3 | Hollywood | Amstetten | 1 |
| 4 | Casa Venezia | Amstetten | 2 |
| 5 | grill.Bar | Amstetten | 2 |
| 6 | Schinakel | Grein | 1 |
Frage: Wie viele Restaurants haben die gleiche Haubenanzahl?
SELECT Haube, COUNT(*) AS AnzahlRestaurants FROM Restaurant GROUP BY Haube;
Ergebnis:
| Haube | AnzahlRestaurants |
|---|---|
| 0 | 2 |
| 1 | 2 |
| 2 | 2 |
Frage: Wie viele Restaurants in Amstetten haben die gleiche Haubenanzahl?
SELECT Haube, COUNT(*) AS AnzahlRestaurants FROM Restaurant WHERE Adr='Amstetten' GROUP BY Haube;
Ergebnis:
| Haube | AnzahlRestaurants |
|---|---|
| 0 | 1 |
| 1 | 1 |
| 2 | 2 |
Gesucht ist eine SQL-Abfrage, die alle Restaurants (rnr und name) und die Anzahl der jeweils gebotenen Speisen ausgibt:
| Relation Restaurant | |||
|---|---|---|---|
| rnr | RName | Adr | Haube |
| 1 | McDonalds | Amstetten | 0 |
| 2 | McDonalds | Ybbs | 0 |
| 3 | Hollywood | Amstetten | 1 |
| 4 | Casa Venezia | Amstetten | 2 |
| 5 | grill.Bar | Amstetten | 2 |
| 6 | Schinakel | Grein | 1 |
| Relation Speise | ||
|---|---|---|
| rnr | SName | Preis |
| 1 | Hamburger | 1 |
| 2 | Hamburger | 1 |
| 2 | Cheeseburger | 1,30 |
| 3 | Hawaii | 8,6 |
| 4 | Hawaii | 9 |
| 5 | Salat | 5 |
| 1 | Salat | 1,80 |
SELECT r.rnr, r.name, COUNT(*) AS Anzahl FROM Restaurant r, Speise s WHERE r.rnr=s.rnr GROUP BY r.rnr, r.name;
1. Schritt: JOIN
| 1 | McDonalds | Amstetten | 0 | Hamburger | 1 |
| 1 | McDonalds | Amstetten | 0 | Salat | 1,80 |
| 2 | McDonalds | Ybbs | 0 | Hamburger | 1 |
| 2 | McDonalds | Ybbs | 0 | Cheeseburger | 1,30 |
| 3 | Hollywood | Amstetten | 1 | Hawaii | 8,6 |
| 4 | Casa Venezia | Amstetten | 2 | Hawaii | 9 |
| 5 | grill.Bar | Amstetten | 2 | Salat | 5 |
2. Schritt: GROUP BY
| 1 | McDonalds | Amstetten | 0 | Hamburger | 1 |
| 1 | McDonalds | Amstetten | 0 | Salat | 1,80 |
| 2 | McDonalds | Ybbs | 0 | Hamburger | 1 |
| 2 | McDonalds | Ybbs | 0 | Cheeseburger | 1,30 |
| 3 | Hollywood | Amstetten | 1 | Hawaii | 8,6 |
| 4 | Casa Venezia | Amstetten | 2 | Hawaii | 9 |
| 5 | grill.Bar | Amstetten | 2 | Salat | 5 |
3. Schritt: COUNT(*) AS Anzahl (pro Gruppe)
| rnr | RName | Anzahl |
|---|---|---|
| 1 | McDonalds | 2 |
| 2 | McDonalds | 2 |
| 3 | Hollywood | 1 |
| 4 | Casa Venezia | 1 |
| 5 | grill.Bar | 1 |
Gesucht sind alle Restaurants (rnr, name), welche mehr als 5 verschiedene (Tipp: Schlüsselwort DISTINCT) Speisen anbieten!
| Relation Restaurant | |||
|---|---|---|---|
| rnr | RName | Adr | Haube |
| 1 | McDonalds | Amstetten | 0 |
| 2 | McDonalds | Ybbs | 0 |
| 3 | Hollywood | Amstetten | 1 |
| 4 | Casa Venezia | Amstetten | 2 |
| 5 | grill.Bar | Amstetten | 2 |
| 6 | Schinakel | Grein | 1 |
| Relation Speise | ||
|---|---|---|
| rnr | SName | Preis |
| 1 | Hamburger | 1 |
| 2 | Hamburger | 1 |
| 2 | Cheeseburger | 1,30 |
| 3 | Hawaii | 8,6 |
| 4 | Hawaii | 9 |
| 5 | Salat | 5 |
| 1 | Salat | 1,80 |
SELECT r.rnr, r.name FROM Restaurant r, Speise s WHERE r.rnr=s.rnr GROUP BY r.rnr, r.name HAVING COUNT(DISTINCT s.name) > 5;
1. Schritt: JOIN
| 1 | McDonalds | Amstetten | 0 | Hamburger | 1 |
| 1 | McDonalds | Amstetten | 0 | Salat | 1,80 |
| 2 | McDonalds | Ybbs | 0 | Hamburger | 1 |
| 2 | McDonalds | Ybbs | 0 | Cheeseburger | 1,30 |
| 3 | Hollywood | Amstetten | 1 | Hawaii | 8,6 |
| 4 | Casa Venezia | Amstetten | 2 | Hawaii | 9 |
| 5 | grill.Bar | Amstetten | 2 | Salat | 5 |
2. Schritt: GROUP BY
| 1 | McDonalds | Amstetten | 0 | Hamburger | 1 |
| 1 | McDonalds | Amstetten | 0 | Salat | 1,80 |
| 2 | McDonalds | Ybbs | 0 | Hamburger | 1 |
| 2 | McDonalds | Ybbs | 0 | Cheeseburger | 1,30 |
| 3 | Hollywood | Amstetten | 1 | Hawaii | 8,6 |
| 4 | Casa Venezia | Amstetten | 2 | Hawaii | 9 |
| 5 | grill.Bar | Amstetten | 2 | Salat | 5 |
3. Schritt: HAVING COUNT(DISTINCT s.name)>5
| rnr | RName |
|---|
Gesucht ist eine SQL-Abfrage, die die rnr und die Anzahl der Haube jener Restaurants angibt, deren teuerste Speise mehr als 8€ kostet. Weiters werden jeweils die Anzahl der Speisen als auch deren Durchschnittspreis ausgegeben.
| Relation Restaurant | |||
|---|---|---|---|
| rnr | RName | Adr | Haube |
| 1 | McDonalds | Amstetten | 0 |
| 2 | McDonalds | Ybbs | 0 |
| 3 | Hollywood | Amstetten | 1 |
| 4 | Casa Venezia | Amstetten | 2 |
| 5 | grill.Bar | Amstetten | 2 |
| 6 | Schinakel | Grein | 1 |
| Relation Speise | ||
|---|---|---|
| rnr | SName | Preis |
| 1 | Hamburger | 1 |
| 2 | Hamburger | 1 |
| 2 | Cheeseburger | 1,30 |
| 3 | Hawaii | 8,6 |
| 4 | Hawaii | 9 |
| 5 | Salat | 5 |
| 1 | Salat | 1,80 |
| 4 | Hühnerstreifensalat | 8,20 |
SELECT r.rnr, r.haube, COUNT(DISTINCT s.name) AS Anzahl, AVG(s.preis) AS AVGPreis FROM Restaurant r, Speise s WHERE r.rnr=s.rnr GROUP BY r.rnr, haube HAVING MAX (s.preis)>8;
1. Schritt: JOIN
| 1 | McDonalds | Amstetten | 0 | Hamburger | 1 |
| 1 | McDonalds | Amstetten | 0 | Salat | 1,80 |
| 2 | McDonalds | Ybbs | 0 | Hamburger | 1 |
| 2 | McDonalds | Ybbs | 0 | Cheeseburger | 1,30 |
| 3 | Hollywood | Amstetten | 1 | Hawaii | 8,6 |
| 4 | Casa Venezia | Amstetten | 2 | Hawaii | 9 |
| 4 | Casa Venezia | Amstetten | 2 | Hühnerstreifensalat | 7,20 |
| 5 | grill.Bar | Amstetten | 2 | Salat | 5 |
2. Schritt: GROUP BY
| 1 | McDonalds | Amstetten | 0 | Hamburger | 1 |
| 1 | McDonalds | Amstetten | 0 | Salat | 1,80 |
| 2 | McDonalds | Ybbs | 0 | Hamburger | 1 |
| 2 | McDonalds | Ybbs | 0 | Cheeseburger | 1,30 |
| 3 | Hollywood | Amstetten | 1 | Hawaii | 8,6 |
| 4 | Casa Venezia | Amstetten | 2 | Hawaii | 9 |
| 4 | Casa Venezia | Amstetten | 2 | Hühnerstreifensalat | 7,20 |
| 5 | grill.Bar | Amstetten | 2 | Salat | 5 |
3. Schritt: HAVING MAX(s.preis)>8
| 3 | Hollywood | Amstetten | 1 | Hawaii | 8,6 |
| 4 | Casa Venezia | Amstetten | 2 | Hawaii | 9 |
| 4 | Casa Venezia | Amstetten | 2 | Hühnerstreifensalat | 7,20 |
4. Schritt: SELECT r.rnr, r.name, COUNT(DISTINCT s.name) AS Anzahl, AVG(s.preis) AS AVGPreis
| rnr | RName | Anzahl | Preis |
|---|---|---|---|
| 3 | Hollywood | 1 | 8,6 |
| 4 | Casa Venezia | 2 | 8,1 |