Wir möchten eine Abfrage erstellen, die einem Programm die Namen aller Lehrer für jeden Kurs und jeden Schüler übergibt. Im späteren Ausdruck gibt es im Formular allerdings nur Platz für 2 Lehrernamen.
Die Ausgangstabelle sieht we folgt aus.
CREATE TABLE Register
(course_nbr INTEGER NOT NULL,
student_name CHAR(10) NOT NULL,
teacher_name CHAR(10) NOT NULL, ..);
![image.png](attachment:image.png)
In [17]:
%load_ext sql
In [18]:
%sql mysql://steinam:steinam@localhost/celko
Out[18]:
In [23]:
%%sql
select * from Register;
Out[23]:
In [22]:
%%sql
SELECT R1.course_nbr, R1.student_name,
MIN(R1.teacher_name) as Teacher_1, NULL
FROM Register AS R1
GROUP BY R1.course_nbr, R1.student_name
HAVING COUNT(*) = 1
UNION
SELECT R1.course_nbr, R1.student_name,
MIN(R1.teacher_name) as Teacher_1,
MAX(R1.teacher_name) as Teacher_2
FROM Register AS R1
GROUP BY R1.course_nbr, R1.student_name
HAVING COUNT(*) = 2
UNION
SELECT R1.course_nbr, R1.student_name,
MIN(R1.teacher_name) as Teacher_1, '--More--' as Teacher_2
FROM Register AS R1
GROUP BY R1.course_nbr, R1.student_name
HAVING COUNT(*) > 2;
Out[22]:
In [ ]:
Benutzt ein Case-Konstrukt zur Abfrage der Anzahl der gefundenen Lehrer
In [25]:
%%sql
SELECT course_nbr, student_name, MIN(teacher_name) as Teacher_1,
CASE COUNT(*) WHEN 1 THEN NULL
WHEN 2 THEN MAX(teacher_name)
ELSE '--More--' END as Teacher_2
FROM Register
GROUP BY course_nbr, student_name;
Out[25]:
In [31]:
%%sql
-- andere Syntax, evtl verständlicher
SELECT course_nbr, student_name, MIN(teacher_name) as Teacher_1,
CASE WHEN COUNT(*) = 1 THEN NULL
WHEN COUNT(*) = 2 THEN MAX(teacher_name)
ELSE '--More--' END as Teacher_2
FROM Register
GROUP BY course_nbr, student_name;
Out[31]:
Stellen Sie sich vor, dass Sie ein großes Restaurant mit 1000 Sitzplätzen führen. Sie möchten eine Übersicht der freien Plätze bzw. der freien Blöcke zwischen besetzten Plätzen.
Bsp:
Besetzt ist Tisch 101, dann würde eine Abfrage wie folgt aussehen.
Start | Ende | Frei |
---|---|---|
1 | 100 | 100 |
102 | 1000 | 999 |
Schreiben Sie eine Routine in ihrer Lieblingsprogrammiersprache zur Lösung des Problems.
Schreiben Sie je ein SQL-Statement, welches Ihnen die jeweils ersten und letzen Plätze einer Lücke findet.
Im obigen Beispiel wären dies die Zahl 1 und 102 für die ersten freien Plätze, sowie 100 und 1000 für die letzten freien Pätze.
In [ ]:
%%sql
create table seats
(seat integer)
insert into seats(seat) values(0);
insert into seats(seat) values(1001);
insert into seats(seat) values(101);
CREATE VIEW Firstseat (seat)
AS SELECT (seat + 1)
FROM seats
WHERE (seat + 1) NOT IN
(SELECT seat FROM seats)
AND (seat + 1) < 1001;
CREATE VIEW Lastseat (seat)
AS SELECT (seat - 1)
FROM seats
WHERE (seat - 1) NOT IN
(SELECT seat FROM seats)
AND (seat - 1) > 0;
-- nutzt die beiden Views
SELECT F1.seat AS start, L1.seat AS finish,
((L1.seat - F1.seat) + 1) AS available
FROM Firstseat F1, Lastseat L1
WHERE L1.seat = (SELECT MIN(L2.seat)
FROM Lastseat AS L2
WHERE F1.seat <= L2.seat)
order by start;
-- braucht keinen view
SELECT (R1.seat + 1) AS start,
(MIN(R2.seat) - 1) AS finish,
abs((R1.seat + 1) - (MIN(R2.seat))) as free
FROM seats AS R1
INNER JOIN
seats AS R2
ON R2.seat > R1.seat
GROUP BY R1.seat
HAVING (R1.seat + 1) < MIN(R2.seat);