Dbs 8
Dbs 8
1. Rekursion in SQL
2. Fortgeschrittenes SQL
8-1
Lernziele fur
\" heute . . .
with ALTER(Durchschnitt) as (
select avg(Jahrgang) from WEINE)
select *
from WEINE, ALTER
where Jahrgang ?`= Durchschnitt - 2
and Jahrgang !`= Durchschnitt + 2
Initialisierung Schritt 1
Abfahrt Ankunft Abfahrt Ankunft
Nuriootpa Penrice Nuriootpa Penrice
Nuriootpa Tanunda Nuriootpa Tanunda
Nuriootpa Seppeltsfield
Nuriootpa Bethany
Schritt 2
Abfahrt Ankunft
Nuriootpa Penrice
Nuriootpa Tanunda
Nuriootpa Seppeltsfield
Nuriootpa Bethany
Nuriootpa Lyndoch
\bullet Zyklusklausel
Weg Zyklus
Nuriootpa-Penrice -
Nuriootpa-Tanunda -
Nuriootpa-Tanunda-Seppeltsfield -
Nuriootpa-Tanunda-Bethany -
Nuriootpa-Tanunda-Bethany-Lyndoch -
Nuriootpa-Tanunda-Bethany-Lyndoch-Tanunda *
\bullet Geschichte
L\"
osung (Zeilen in Spalten): Aggregatfilter
select Jahr, sum(Umsatz) filter (where Quartal=1) Q1,
sum(Umsatz) filter (where Quartal=2) Q2,
sum(Umsatz) filter (where Quartal=3) Q3,
sum(Umsatz) filter (where Quartal=4) Q4
from LDATA
group by Jahr
L\"
osung (Spalten in Zeilen): union all
select 1 as Quartal, Jahr, Q1 as Umsatz from RDATA
union all
select 2 as Quartal, Jahr, Q2 as Umsatz from RDATA
union all
select 3 as Quartal, Jahr, Q3 as Umsatz from RDATA
union all
select 4 as Quartal, Jahr, Q4 as Umsatz from RDATA
L\"
osung: linker äußerer Verbund
select Vorname, Name, [Link] as Mobil, [Link] as Arbeit
from (Personal P left outer join Kontakt K
on [Link] = [Link] and [Link] = 'Mobil')
left outer join Kontakt K2
on [Link] = [Link] and [Link] = 'Arbeit'
Funktion(arg)
OVER( )
Partitionierungs- Ordnungs-
klausel klausel
Fenster
Partitionierung für jedes Attribut
Ordnung innerhalb
des Ergebnisses ohne Verdichtung:
eines Attributs Festlegung des
jeder Eingangswert ↦ Ergebniswert
8 - 27 VL Datenbanksysteme Sattler / Saake
Aggregationsfensters
Window-Funktionen: Prinzip
Was liefert . . .
select count(*) over() count
from RACE 9
9
9
...
und . . .
count
select count(*) over(order by Zeit)
from RACE 1
2
3
...
9
select * from (
select Name, Zeit, rank() over (order by Zeit) Rang
from RACE
where Distanz = 'M') T
where Rang !`= 2
select * from (
select Name, Distanz, Zeit,
rank() over (partition by Distanz order by Zeit) Rang
from RACE) T
where Rang !`= 2
Wert
0:03 4.9 4
0:04 4.4 3.5
0:05 4.1 3
2.5
0:06 3.9 2
0:07 4.5 0 1 2 3 4 5 6 7 8 9 10
0:08 4.3 Zeit
0:09 4.1
L\"
osung: Window-Funktion mit Aggregationsfenster
Name Hobby
Kevin Schach
Kevin Musik
Corinna Parties
Martin Handball
Martin Musik
Katja Handball
Katja Musik
Losung:
\" 7 verschiedene Varianten in Celko’s SQL Puzzles; hier:
Mengentheorie
Teilschritt: verschiedene Hobbies, z.B. für Kevin und Martina vs. Katja
und Martin
select [Link] from Hobbies as h3
where 'Kevin' = [Link]
except
select [Link] from Hobbies as h4
where 'Martina' = [Link])
z.B. für aktuelle Zeit (current time) oder gegebene Zeit (time
'8:00')
Losung:
\" Finde minimale Abfahrtszeit, die nach der gewünschten Zeit
liegt
select * from Fahrplan f1
where [Link] = (
select min([Link]) from Fahrplan f2
where [Link] ?`= time '8:05')
Name Studiengang
Kevin Informatik
Heike BWL
Corinna Mathematik
Martina BWL
Ronny BWL
Katharina Informatik
Losung:
\" Bestimmung der Anzahl des häufigsten Wertes + having
count(*) bezogen auf diesen Wert
select Studiengang, count(*)
from Students
group by Studiengang
having count(*) ?`= all (
select count(*)
from Students group by Studiengang)
Losung:
\" systematisch alle Felder mit Werten von 1 bis 9 auffüllen und
prüfen
Quellen: [Link]
oracle-rdbms-11gr2-solving-a-sudoku-using-recursive-subquery-facto
[Link]
Hilfsfunktionen (PostgreSQL)
\bullet generate series(s,e): erzeugt eine Folge von Werten von s bis e
\bullet substr(s, start, len): liefert einen Substring der Länge len
aus s beginnend bei start
\bullet repeat(s, n): erzeugt einen String durch n-fache Wiederholung
von s
\bullet position(sub in s): liefert die Position von sub in s
-- fur
\" ind = 3
select * from generate series(1, 9) lp
-- Zeile: 1, 2, 3, 4, . . .
where z.z = substr(s, ((ind - 1) / 9) * 9 + lp, 1)
-- Spalte: 3, 12, 21, 30, . . .
or z.z = substr(s, mod(ind - 1, 9) - 8 + lp * 9, 1)
-- Block: 1, 2, 3, 10, 11, 12, . . .
+ ((ind - 1) / 27) * 27 + lp + ((lp - 1) / 3) * 6, 1))
\bullet regexp replace (txt, pat, repl, flag): ersetzt in txt einen
zum Muster pat passenden String durch repl
\bullet regexp split to table (txt, pat): teilt den String txt anhand
des Musters pat und liefert eine Relation
...
select regexp replace(regexp split to table(
regexp replace(s, '.9(?!$)', '\setminus \&-', 'g'), '-'),
'.3(?!$)', '\setminus \&---', 'g')
from x
where position(' ' in s) = 0
\bullet Zuweisung
set var = 42;
\bullet Schleifen
loop Anweisungen end loop;
while Bedingung do
Anweisungen end while;
repeat Anweisungen
until Bedingung end repeat;
Ausnahmebehandlung
begin
declare exit handler for ConditionName
begin
-- \mathrm{A}\mathrm{n}\mathrm{w}\mathrm{e}\mathrm{i}\mathrm{s}\mathrm{u}\mathrm{n}\mathrm{g}\mathrm{e}\mathrm{n} \mathrm{z}\mathrm{u}\mathrm{r} \mathrm{A}\mathrm{u}\mathrm{s}\mathrm{n}\mathrm{a}\mathrm{h}\mathrm{m}\mathrm{e}\mathrm{b}\mathrm{e}\mathrm{h}\mathrm{a}\mathrm{n}\mathrm{d}\mathrm{l}\mathrm{u}\mathrm{n}\mathrm{g}
end
-- \mathrm{A}\mathrm{n}\mathrm{w}\mathrm{e}\mathrm{i}\mathrm{s}\mathrm{u}\mathrm{n}\mathrm{g}\mathrm{e}\mathrm{n}, \mathrm{d}\mathrm{i}\mathrm{e} \mathrm{A}\mathrm{u}\mathrm{s}\mathrm{n}\mathrm{a}\mathrm{h}\mathrm{m}\mathrm{e}\mathrm{n} \mathrm{a}\mathrm{u}\mathrm{s}\mathrm{l}\"
\mathrm{o}\mathrm{s}\mathrm{e}\mathrm{n} \mathrm{k}\"
\mathrm{o}\mathrm{n}\mathrm{n}\mathrm{e}\mathrm{n}
end
Funktionsdefinition
create function geschmack (rz int)
returns varchar(20)
begin
return case
when rz !`= 9 then 'Trocken'
when rz ?` 9 and rz !`= 18 then 'Halbtrocken'
when rz ?` 18 and rz !`= 45 then 'Lieblich'
else 'S\"
u{\ss}'
end
end
\bullet Prozedurdefinition
create procedure weinliste (in erz varchar(30),
out wliste varchar(500))
begin
declare pos integer default 0;
Funktionsdefinition
create function geschmack (rz int) returns varchar(20) as $$
begin
return case when rz !`= 9 then 'Trocken'
when rz ?` 9 and rz !`= 18 then 'Halbtrocken'
when rz ?` 18 and rz !`= 45 then 'Lieblich'
else 'S\"
u{\ss}'
end;
end;
$$ language plpgsql;