Bases de données cours 5 www.liafa.univ-paris-diderot.fr/~zielonka
R a b c 1 8 1 1 6 2 2 11 1 2 6-5 S c d 2 6 3 2 3 1 13 9 select sum(a*d) as X, C from R natural join S where C in (select a+1 from R) group by C order by x asc ; 3 0 6 3 3 0 4 4 4 4 7 2 5 0 3 select c, count(*) as count from R natural left join S where a>= 2 group by c having count(*) > 1;
trouver les lecteurs qui ont emprunté cette année plus que l année dernière : select nom, prenom from lecteur L where (select count(*) from emprunt E where extract(year from date_emprunt)=2015 and E.id_lecteur=L.id_lecteur) > (select count(*) from emprunt E where extract(year from date_emprunt)=2014 and E.id_lecteur=L.id_lecteur) ;
pour plus de souplesse remplacer 2015 par EXTRACT(YEAR FROM CURRENT_DATE) et 2014 par EXTRACT(YEAR FROM CURRENT_DATE) - 1
employe(nom, prénom,sexe,salaire,departement) trouver les employés qui gagnent plus que le salaire moyen dans leur département : select nom, prénom, salaire from employe X where salaire > (select avg(salaire) from employe Y X.departement = Y.departement);
trouver les livres qui se trouvent dans le catalogue de livres et dont la bibliothèque ne possède aucun exemplaire : select titre from livre L where NOT exists (select * from exemplaire E where E.id_livre = L.id_livre);
LIMIT OFFSET SELECT list-select FROM tables LIMIT nombre OFFSET nombre; LIMIT donne le limite du nombre de lignes à afficher, les lignes supplémentaires sont ignorées. OFFSET indique le nombre de lignes sautées au début de la réponse.
SELECT nom, prénom, salaire FROM employe ORDER by salaire LIMIT 10 OFFSET 5; Dans la table employe trouver le salaire median (et une personne qui reçoit ce salaire) : select nom, prénom, salaire from employe limit 1 offset (select count(*) from employe)/2;
WITH WITH nom_table( liste_attributs ) AS (select ) requête SELECT ; WITH permet de définir une table auxiliaire qui sera utilisée dans la requête SELECT principale. Il est possible de définir plusieurs tables auxiliaires dans WITH : WITH table1 as(select ), table2 as (select ) requête_select_principale;
WITH NB_EMPRUNT(nb) AS (select count(*) from lecteur natural join emprunt group by id_lecteur) select nom, prenom from lecteur natural join emprunt group by id_lecteur, nom, prenom having count(*)=(select max(nb) from NB_EMPRUNT);
Jointures (complément) T1 natural join T2 T1 natural left join T2 T1 natural right join T2 T1 natural full join T2 T1 cross join T2 (la même chose que T1,T2) T1 joint T2 on join_condition T1 left join T2 on join_condition T1 right join T2 on join_condition T1 full join T2 on join_condition
T1 T2 A B C D 1 11 8 12 6 13 0 1 3 1 5 2 select D, Max(A) as MA from T1 left join T2 on T1.A<T2.C group by D; T1 left join T2 on T1.A < T2.C A B C D 1 11 3 1 1 11 5 2 8 12 null null 6 13 null null le résultat de select D MA 1 1 2 1 null 8
Quelques exemples Trouver les lecteurs qui ont emprunté au moins 10 livres différents (on compte les livres, pas les exemplaires de livres) : select nom, prenom from lecteur L where (select count(distinct id_livre) from emprunt E natural join livre where E.id_lecteur = L.id_lecteur) >= 10;
Trouver les lecteurs qui n ont emprunté aucun livre d Alexandre Dumas : select nom, prenom from lecteur L where not exists ((select id_exemplaire from emprunt where id_lecteur = L.id_lecteur) intersect (select id_exemplaire from livre natural join livre_auteur natural join auteur natural join exemplaire where lower(nom) = 'dumas' and lower(prenom) = 'alexandre')); tous les id_exemplaire de livres empruntés par le lecteur L tous les id_exemplaire des livres de Dumas
Requêtes avec les conditions d inclusion ou d égalité des ensembles Est-ce qu un étudiant a pris tous les cours obligatoires? A B ou A = B Est-ce qu un lecteur a lu tous les livres de Alexandre Dumas? Trouver les lecteurs qui ont lu tous les livres d Alexandre Dumas et aucun autre livre.
Requêtes avec les conditions d inclusion ou d égalité des ensembles A B ou A = B A inclus dans B équivalent à la condition NOT EXISTS (A EXCEPT B) A = B équivalent à (A inclus dans B) AND (B inclus dans A)
trouver les lecteurs qui ont lu tous les livres d Alexandre Dumas : select nom, prenom from lecteur L where not exists ((select id_livre from livre natural join livre_auteur natural join auteur where nom='dumas' and prenom='alexandre') except (select id_livre from livre natural join exemplaire natural join emprunt E where E.id_lecteur = L.id_lecteur) ); rouge - l ensemble de id_livres d Alexandre Dumas bleu - l ensemble de id_livre lus par le lecteur L
Les vues CREATE VIEW nom_view(liste de colonnes) AS (SELECT ); créer une vue d emprunt courants: create view emprunts_courants as (select date_emprunt, id_exemplaire, id_lecteur, date_prevu from emprunt where date_effective is null);
Les lecteurs en retard de retour : select distinct nom, prenom from emprunts_courants natural join lecteur where date_prevu < current_date; Une vue emprunts_courants n est pas une table fixe, emprunts_courants change automatiquement et donne toujours l état actuel (une vue) des emprunts en cours. Une vue peut être utilisée dans les requêtes SELECT partout où on utilise les tables.
Sous requêtes dans FROM drop table if exists notes; drop table if exists etudiant; create table etudiant( id_etudiant int primary key, nom varchar, prenom varchar); create table notes( id_etudiant int references etudiant, note decimal(4,1));
calculer la moyenne de deux meilleures notes de Jacques Dupont: select cast( avg(note) as decimal(4,2)) FROM (Select note from notes natural join etudiant where nom = 'Dupont' and prenom='jacques' order by note desc limit 2) as toto; en rouge les deux meilleures notes de Jacques Il est obligatoire de nommer la table qui est définie dans FROM.
Calculer la moyenne de chaque étudiant, ne retenir que les deux meilleures notes de chacun : select nom, prenom, (select cast( avg(note) as decimal(4,2)) FROM (Select note from notes where id_etudiant = E.id_etudiant order by note desc limit 2) as toto) from etudiant E;
les requêtes précédentes étaient difficiles étaient difficiles à concevoir parce que la table notes n avait pas de clé. Ajoutons une clé primaire à la tables de notes : create table etudiant( id_etudiant int primary key, nom varchar, prenom varchar); create table notes( id_note integer primary key, id_etudiant int references etudiant, note decimal(4,1));
La requêtes : calculer la moyenne de trois meilleures notes de chaque étudiant devient bien plus facile à concevoir: select nom, prénom, avg(note) as moyenne from notes E natural join etudiant where E.id_note IN (select id_note from notes N where N.id_etudiant = E.id_etudiant order by note desc limit 3) group by id_etudiant, nom, prénom