Um die folgenden Abfragen in SQL an Ihre Datenbank user_[loginname]_WM2006 stellen zu können, müssen Sie zunächst einen Teil der Abfrage als Sicht (View) zur Verfügung stellen und mit einer select-Abfrage darauf zugreifen. Formulieren Sie anschließend mit Hilfe der Views die folgenden Abfragen in SQL und überprüfen Sie sie anhand Ihrer Datenbank:
Definieren Sie zunächst eine View, die die beiden Mannschaften der Spiele sowie die erzielten Tore auflistet. Beachten Sie dabei, auch die Eigentore einer Mannschaft als Gegentore zu zählen.
Definieren Sie zunächst eine View, die die Anzahl der Spiele pro Mannschaft auflistet, sowie eine View, die die Anzahl der Gegentore pro Mannschaft auflistet. Beachten Sie dabei wieder, die Eigentore als Gegentore zu zählen.
Musterlösung vom 08.06.2008:
Es ergeben sich folgende Abfragen:
1.
-- Eine Sicht, die die Verwarnungen pro Spiel ausgibt
create view VerwJeSpiel as
select SpielID, count(*) as AnzVerw
from Verwarnungen
group by SpielID
-- Drei verschiedene Abfragen
-- SELECT mit 'NOT EXISTS'
select sp.Mannschaft1, sp.Mannschaft2, s.Name, v1.AnzVerw
from Spiele sp, VerwJeSpiel v1, Schiedsrichter s, leitet l
where sp.SpielID = v1.SpielID
and l.SpielID = v1.SpielID
and l.SID = s.SID
and l.Funktion = 'Referee'
and not exists
(select *
from VerwJeSpiel v2
where v1.AnzVerw < v2.AnzVerw)
-- SELECT mit 'IN'
select sp.Mannschaft1, sp.Mannschaft2, s.Name, v1.AnzVerw
from Spiele sp, VerwJeSpiel v1, Schiedsrichter s, leitet l
where sp.SpielID = v1.SpielID
and l.SpielID = v1.SpielID
and l.SID = s.SID
and l.Funktion = 'Referee'
and v1.AnzVerw in
(select max(AnzVerw)
from VerwJeSpiel)
-- SELECT mit 'HAVING'
select sp.Mannschaft1, sp.Mannschaft2, s.Name, v1.AnzVerw
from Spiele sp, VerwJeSpiel v1, Schiedsrichter s, leitet l
where sp.SpielID = v1.SpielID
and l.SpielID = v1.SpielID
and l.SID = s.SID
and l.Funktion = 'Referee'
group by sp.Mannschaft1, sp.Mannschaft2, s.Name, v1.AnzVerw
having v1.AnzVerw =
(select max(AnzVerw)
from VerwJeSpiel)
2.
-- Eine View, die die Spiele der Vorrunde mit den jeweils von beiden
-- Mannschaften erzielten Toren auflistet
create view Vorrunde2 as
select sp.*,
(select count(*)
from Tore t, Spieler s
where t.SpielID = sp.SpielID
and t.SpielerNr = s.SpielerNr
and ((s.Land = sp.Mannschaft1
and t.Spielsituation != 'own goal')
or (s.Land = sp.Mannschaft2
and t.Spielsituation = 'own goal'))) as Tore1,
(select count(*)
from Tore t, Spieler s
where t.SpielID = sp.SpielID
and t.SpielerNr = s.SpielerNr
and ((s.Land = sp.Mannschaft2
and t.Spielsituation != 'own goal')
or (s.Land = sp.Mannschaft1
and t.Spielsituation = 'own goal'))) as Tore2
from Spiele sp
where Runde like 'Group%';
-- Abfrage auf der View
-- Die inneren selects berechnen mit Hilfe des case-Operators die Punkte pro
-- Spiel, jewels fuer beide Mannschaften
-- Das aeussere select summiert die Punkte pro Mannschaft auf, sortiert
-- entsprechend
select t.Runde, t.Land, sum(t.Punkte) as Gesamtpunkte
from
(select Runde, Mannschaft1 as Land,
(case when Tore1 < Tore2 then 0
when Tore1 = Tore2 then 1
when Tore1 > Tore2 then 3
end) as Punkte
from Vorrunde
union all
select Runde, Mannschaft2 as Land,
(case when Tore2 < Tore1 then 0
when Tore2 = Tore1 then 1
when Tore2 > Tore1 then 3
end) as Punkte
from Vorrunde) t
group by t.Runde, t.Land
order by t.Runde asc, Gesamtpunkte desc;
3.
-- Eine View, die die Spiele pro Mannschaft zaehlt
create View SpieleJeMannschaft as
select m.Land, count(*) as Anzahl
from Spiele s, Mannschaften m
where s.Mannschaft1 = m.Land
or s.Mannschaft2 = m.Land
group by m.Land
-- Das MySQL keine Subselect in der 'from'-clause in Views zulaesst, wird eine
-- Hilfsview definiert, die fuer jedes Gegentor einmal die Mannschaft
-- auflistet, die das Tor kassiert hat.
create view Subselect as
select s.Mannschaft1 as Land
from Spiele s, Tore t, Spieler sp
where s.SpielID = t.SpielID
and s.Mannschaft2 = sp.Land
and sp.SpielerNr = t.SpielerNr
and t.Spielsituation != 'own goal'
union all
select s.Mannschaft2 as Land
from Spiele s, Tore t, Spieler sp
where s.SpielID = t.SpielID
and s.Mannschaft1 = sp.Land
and sp.SpielerNr = t.SpielerNr
and t.Spielsituation != 'own goal'
union all
select sp.Land as Land
from Spieler sp, Tore t
where sp.SpielerNr = t.SpielerNr
and t.Spielsituation = 'own goal'
-- Select, welches ueber die Hilfsview laeuft und die Eintraege pro Mannschaft,
-- also die Anzahl der Gegentore zaehlt
create view GegentoreJeLand as
(select Land, count(*) as Gegentore
from Subselect
group by Land)
-- Eigentliche Abfrage
-- Das erste innere Select teilt die Anzahl der Gegentore durch die Anzahl der
-- Spiele fuer jede Mannschaft. Das zweite innere select ergaenzt Mannschaften,
-- die keine Gegentore (ausser im Elfmeterschiessen) bekommen haben.
-- Aeusseres select wird benoetigt, um auf der Vereinigungsmenge (union) der
-- beiden inneren Selects sortieren zu koennen
select *
from (select s.Land, g.Gegentore / s.Anzahl as Rang
from SpieleJeMannschaft s, GegentoreJeLand g
where g.Land = s.Land
union
select m.Land, 0 as Rang
from Mannschaften m
where m.Land not in (select s.Land from GegentoreJeLand s)) tmp
order by Rang