BARS ET BUVEURS DE BIERES (d'après Victor VIANU)

Schéma :
Servir(Bar, Bière)
Fréquenter(Buveur, Bar)
Aimer(Buveur, Bière)
Questions :

Q1 - Les bars qui servent une bière appréciée par 'Dupont'
Q2 - Les buveurs qui vont dans les mêmes bars que Dupont
Q3 - Les buveurs qui fréquentent au moins un bar où l'on sert une bière qu'ils aiment
Q4 - Les buveurs qui ne fréquentent aucun bar où l'ont sert une bière qu'ils aiment
Q5 - Les buveurs qui fréquentent tous les bars
Q6 - Les buveurs qui fréquentent tous les bars qui servent au moins une bière qu'ils aiment
Q7 - Les buveurs qui ne fréquentent que les bars qui servent une bière qu'ils aiment
Q8 - Donner pour chaque buveur, le nombre de bars servant une bière qu'ils aiment
Q9 - Les buveurs qui fréquentent au moins 2 bars où l'on sert une bière qu'ils aiment



Q1 - Les bars qui servent une bière appréciée par 'Dupont'

Calcul Relationnel des T uples (CRT)

{b:Bar / EXISTS s FROM Servir, EXISTS a FROM Aimer, s.Bière = a.Bière AND a.Buveur = 'Dupont' AND b = s.Bar}

SQL>

SELECT Bar
FROM Aimer A, Servir S
WHERE S.Bière = A.bière AND Buveur ='Dupont';
Algèbre

Retour à la liste de questions


Q2 - Les buveurs qui vont dans les mêmes bars que Dupont

CRT

{b:Buveur / EXISTS f1 FROM Fréquenter, EXISTS f2 FROM Fréquenter, f1.Bar = f2.Bar AND f1.Buveur = 'Dupont' AND f2.Buveur = b}

SQL>

SELECT F1.Buveur
FROM Fréquenter F1, Fréquenter F2
WHERE F1.Bar = F2.Bar AND F2.Buveur = 'Dupont';
Algèbre

Retour à la liste de questions


Q3 - Les buveurs qui fréquentent au moins un bar où l'on sert une bière qu'ils aiment

CRT

{b:Buveur / EXISTS f FROM Fréquenter, EXISTS s FROM Servir, EXISTS a FROM Aimer, a.Bière = s.Bière ANDs.Bar = f.Bar AND f.Buveur = a.buveur AND f.Buveur = b}

SQL>

SELECT F.Buveur
FROM Fréquenter F, Aimer A, Servir S
WHERE A.Bière = S.Bière AND S.Bar = F.Bar AND A.Buveur = F.Buveur ;
Algèbre

Retour à la liste de questions


Q4 - Les buveurs qui ne fréquentent aucun bar où l'ont sert une bière qu'ils aiment

CRT

{b:Buveur / WHICHEVER f FROM Fréquenter, f.buveur = b => (WHICHEVER s FROM Servir, WHICHEVER a FROM Aimer, a.Bière != s.Bière OR s.Bar != f.Bar OR f.Buveur != a.buveur}

Règles de transformation pour passer à la formulation SQL :

- A => B est équivalent à NOT A OR B

{b:Buveur / WHICHEVER f FROM Fréquenter, f.Buveur = b => (WHICHEVER s FROM Servir, WHICHEVER a FROM Aimer, a.Bière != s.Bière OR s.Bar != f.Bar OR f.Buveur != a.Buveur)}

- Eliminer WHICHEVER à l'aide de :

WHICHEVER x, f (x) équivalent à NOT EXISTS x, NOT f (x)

- Un niveau d'imbrication avec "NOT IN" pour chaque NOT EXISTS x .
 

{b:Buveur / NOT EXISTS f FROM Fréquenter, f.buveur = b AND NOT EXISTS s FROM Servir, NOT EXISTS a FROM Aimer, (a.Bière = s.Bière AND s.Bar = f.Bar AND f.Buveur = a.buveur)}

SQL>
SELECT Buveur
FROM Fréquenter F
WHERE Buveur NOT IN
(SELECT Buveur
FROM Aimer A, Servir S
WHERE S.Bar = F.Bar
     AND S.Bière = A.Bière );


Algèbre

Retour à la liste de questions


Q5 - Les buveurs qui fréquentent tous les bars

CRT

{b:Buveur / WHICHEVER f1 FROM Fréquenter, EXISTS f2 FROM Fréquenter, f2.Bar = f1.Bar AND f2.Buveur = b}

Elimination de WHICHEVER

{b:Buveur / NOT EXISTS f1 FROM Fréquenter, NOT EXISTS f2 FROM Fréquenter, (f2.Bar = f1.Bar AND f2.Buveur = b)}

SQL>

SELECT Buveur
FROM Fréquenter
WHERE Buveur NOT IN
(SELECT F1.Buveur
FROM Fréquenter F1, Fréquenter F2
WHERE F1.Buveur NOT IN
(SELECT Buveur
FROM Fréquenter
WHERE Bar=F2.Bar)
);
Algèbre

Retour à la liste de questions


Q6 - Les buveurs qui fréquentent tous les bars qui servent au moins une bière qu'ils aiment
CRT

{b:Buveur / WHICHEVER a FROM Aimer, WHICHEVER s FROM Servir, s.Bière = a.Bière AND a.Buveur = b => EXISTS f FROM Fréquenter, f.Bar = s.Bar AND f.Buveur = b }

Transformation

{b:Buveur / NOT EXISTS a FROM Aimer, NOT EXISTS s FROM Servir, (s.Bière = a.Bière AND a.Buveur = b AND NOT EXISTS f FROM Fréquenter, (f.Bar = s.Bar AND f.Buveur = b)) }

REM La requête en SQL revient à rechercher le complémentaire des buveurs qui ne fréquentent pas au moins un bar qui sert une bière qu'ils aiment:

NON(les buveurs qui ne fréquentent pas au moins un bar qui sert une bière qu'ils aiment)

SQL>

SELECT Buveur
FROM Fréquenter F
WHERE Buveur NOT IN
(SELECT A.Buveur
FROM Servir S, Aimer A
WHERE S.Bière=A.Bière
AND A.Buveur NOT IN
(SELECT Buveur
FROM Fréquenter
WHERE Bar=S.Bar)
);
Algèbre

Retour à la liste de questions


Q7 - Les buveurs qui ne fréquentent que les bars qui servent une bière qu'ils aiment

CRT

{b:Buveur / WHICHEVER f FROM Fréquenter, f.Buveur = b => EXISTS a FROM Aimer, EXISTS s FROM Servir, s.Bière = a.Bière AND f.Bar = s.Bar }

Transformation

{b:Buveur / NOT EXISTS f FROM Fréquenter, (f.Buveur = b AND NOT EXISTS a FROM Aimer, NOT EXISTS s FROM Servir, (s.Bière = a.Bière AND f.Bar = s.Bar)) }
 

REM La requête revient à rechercher le complémentaire des buveurs qui fréquentent au moins un bar qui ne sert aucune bière qu'ils aiment :
     NON (les buveurs qui fréquentent au moins un bar qui ne sert aucune bière qu'ils aiment)

SQL>

SELECT Buveur
FROM Fréquenter
WHERE Buveur NOT IN
(SELECT Buveur
FROM Fréquenter F
WHERE Bar NOT IN
(SELECT Bar
FROM Servir S, Aimer A
WHERE A.Buveur = F.Buveur
And S.Bière = A.Bière)
);
Ce qui est équivalent à
SELECT Buveur
FROM Fréquenter
WHERE Buveur NOT IN
(SELECT Buveur
FROM Fréquenter F
WHERE Buveur NOT IN
(SELECT Buveur
FROM Servir S, Aimer A
WHERE S.Bar = F.Bar
       And S.Bière = A.Bière)
);
Algèbre

Retour à la liste de questions


Q8 - Donner pour chaque buveur, le nombre de bars servant une bière qu'ils aiment

SQL>

SELECT Buveur, COUNT(DISTINCT Bar)
FROM Servir S, Aimer A
WHERE S.Bière = A.Bière
GROUP BY Buveur;
Retour à la liste de questions


Q9 - Les buveurs qui fréquentent au moins 2 bars où l'on sert une bière qu'ils aiment

SQL>

SELECT Buveur
FROM Servir S, Aimer A, Fréquenter F
WHERE S.Bière = A.Bière AND A.Buveur = F.Buveur AND F.Bar = S.Bar
GROUP BY Buveur
HAVING COUNT(Bar)>2;
Retour à la liste de questions