Langage Manipulation de Données 2 : requêtes imbriquées
2024-09-27
Les deux tables doivent avoir des schémas identiques
EXCEPT
`Fournisseur (NomF, VilleF, AdresseF)`
`Piece(NomP, Prix, Couleur)`
`Livraison(NumLiv, NomP, NomF, DateLiv, Quantite)`
Fournisseurs qui ont livré la pièce x22
mais pas la pièce x21
IN, EXISTS, ALL, ANY, LATERAL
Le résultat d’une requête SQL est un ensemble de tuples… donc une relation.
Dans la clause WHERE
d’une requête, on peut utiliser une fonction d’une autre requête, appelée sous-requête
IN, EXISTS, ALL, ANY
sont des fonctions qui prennent une sous-requête (une relation) en argument.
Dans une sous-requête, on peut se référer à des attributs des tables de la clause FROM
.
Pour chaque ligne d’un item FROM
qui fournit la colonne référencée, l’item LATERAL
est évalué en utilisant cette ligne. Les lignes du résultat sont jointes avec la ligne qui a servi à les calculer.
On peut utiliser ces résultats comme données d’une autre requête
Moyens : utiliser des fonctions de table dans la clause WHERE
.
IN
Opérateur IN
déjà vu pour exprimer que l’attribut est à valeur dans une certaine liste
Nouvelle utilisation de IN
avec des sous-requêtes.
Evaluée à vraie si
IN
Lister les villes de fournisseurs qui ont livré la pièce ‘x21’.
IN
Lister les couleurs de pièces livrées par des fournisseurs de Paris
IN
Utilisation ci-dessus pas très utile mais…
Pratique à utiliser sous la forme NOT IN
Lister les noms de pièces qui n’ont jamais été livrées.
Equivalence en algèbre relationnelle :
\[\pi_{\text{NomP}}(\text{Piece}) - \pi_{\text{NomP}}(\text{Livraison})\]
…. Une des façons de coder la différence en SQL
IN
Les capitales dont la population est plus grande que la moitié de la population du pays
ANY
, ALL
Deux nouveaux opérateurs manipulant des sous-requêtes : ANY
, ALL
évaluée à vraie si au moins un des résultats de la sous requête vérifie la comparaison avec <attributs>
évaluée à vraie si tous les résultats de la sous-requête vérifient la comparaison avec <attributs>
<attributs>
: peut être une liste d’attributs
ANY
, ALL
Alternative au IN
lister les noms de fournisseurs qui ont livré la pièce ‘x21’.
ANY
, ALL
Information sur la commande dont la quantité de ièces livrées était la plus importante.
ANY
, ALL
Noms et prix des pièces livrées les plus chères
ANY
, ALL
La ville la plus peuplée de chaque pays
EXISTS
est évaluée à vraie si la sous-requête renvoie au moins un résultat.
Nom et prix des pièces qui ont été livrées
Différence avec ANY
L’utilisation de EXISTS
s’apparente à une condition booléenne.
Pas de test sur la valeur d’un attribut particulier.
EXISTS
Nom des Fournisseurs ayant livré la pièce x21 mais qui n’ont jamais livré la pièce a22.
EXISTS
Les régions qui ont au moins une langue officielle :
PostgreSQL 9.3 has a new join type! Lateral joins arrived without a lot of fanfare, but they enable some powerful new queries that were previously only tractable with procedural code. In this post, I’ll walk through a conversion funnel analysis that wouldn’t be possible in PostgreSQL 9.2.
LATERAL
Important
Les sous-requêtes d’une clause FROM
peuvent être précédées du mot-clé LATERAL
On peut alors faire référence à des colonnes des éléments précédents de la clause FROM
When a FROM item contains
LATERAL
cross-references, evaluation proceeds as follows: for each row of theFROM
item providing the cross-referenced column(s), or set of rows of multipleFROM
items providing the columns, theLATERAL
item is evaluated using that row or row set’s values of the columns. The resulting row(s) are joined as usual with the rows they were computed from. This is repeated for each row or set of rows from the column source table(s).
Les arguments de la fonction peuvent contenir des références à des colonnes des items précédents de la clause FROM
.
Pour chaque ligne d’un item FROM
qui fournit la colonne référencée, l’item LATERAL
est évalué en utilisant cette ligne. Les lignes du résultat sont jointes avec la ligne qui a servi à les calculer
On peut parler de sous-requête paramétrée
LATERAL
SELECT name_country, name_city
FROM country, LATERAL (
SELECT name_city
FROM city
WHERE city.countrycode=country.countrycode
) ss
ORDER BY name_country;
équivalent à
LATERAL
est surtout utilisé quand la colonne référencée est nécessaire au calcul des lignes à joindre
LATERAL
en action sur world
name_country | name_city |
---|---|
Spain | A Coruña (La Coruña) |
Germany | Aachen |
Denmark | Aalborg |
Nigeria | Aba |
Iran | Abadan |
Brazil | Abaetetuba |
Russian Federation | Abakan |
Canada | Abbotsford |
Nigeria | Abeokuta |
… | … |
SELECT name_country, name_city, lifeexpectancy
FROM (
SELECT countrycode, name_country, lifeexpectancy
FROM country
WHERE gnpold >0 AND gnp / gnpold > 1.1
) AS better_off
JOIN LATERAL (
SELECT c.countrycode, name_city #<<
FROM country c
JOIN city ON (capital = id)
WHERE
better_off.countrycode=c.countrycode AND
population_city> 2000000
) AS big_capital
ON TRUE ;
Country | City | Life expectancy |
---|---|---|
Iran | Teheran | 69.7 |
Congo, The Democratic Republic of the | Kinshasa | 48.8 |
Turkey | Ankara | 71.0 |
Could be useful for implementing exploratory pipelines into postgresql without to much tears and sweat.
WITH
Une clause WITH
permet d’écrire des requêtes intermédiaires et de décomposer une requête complexe
Ces expressions/requêtes sont souvent désignées par le vocable Common Table Expressions
ou CTEs
Les CTEs (éléments d’une clasuse WITH
) peuvent être des requêtes, mais aussi des expressions de manipulation (mise à jour, insertion, suppression) de données
Les CTEs permettent de coller plus fidèlement à l’algèbre relationnelle que les requêtes imbriquées
WITH better_off AS (
SELECT countrycode, name_country, lifeexpectancy, capital
FROM country
WHERE gnpold >0 AND gnp / gnpold > 1.1
),
big_capital AS (
SELECT id, countrycode
FROM city
WHERE population > 2000000
)
SELECT bo.countrycode, name_country, lifeexpectancy
FROM better_off bo JOIN big_capital bc ON
(bo.countrycode=bc.countrycode AND bc.id=bo.capital) ;
Requêtes SQL imbriquées
MA15Y030 – Bases de Données – L3 MIASHS – UParis Cité