Interroger une base RO : Utilisation des tables imbriquées
Dans ce troisième exercice, vous expérimenterez la manipulation des collections implémentées sous forme de tables imbriquées.
Question
Ecrivez une requête permettant de renvoyer le nombre de produits achetés par le client 1.
Indice
Il faut utiliser la pseudo-jointure TABLE() entre la table des factures et la table imbriquée des lignes de facture.
SELECT ...
FROM Facture f, TABLE(f.Lignes_facture) lf
WHERE ...
Solution
SELECT SUM(lf.qte) AS nombre
FROM Facture f, TABLE(f.Lignes_facture) lf
WHERE f.fkClient.num = 1;
Question
Ecrivez une requête permettant de renvoyer les numéros et noms des clients ayant payé au moins une facture avec plus de 5 articles.
Indice
Faites un regroupement sur les numéros de client, noms des client et factures.
Solution
SELECT DISTINCT f.fkClient.num AS numero, f.fkClient.nom AS nom
FROM Facture f, TABLE(f.Lignes_facture) lf
GROUP BY f.fkClient.num,f.fkClient.nom, f.num
HAVING SUM(lf.qte) > 5;
Notons que La clause GROUP BY
spécifie que l'on regroupe les enregistrements par numéro de client, nom de client et facture. Dans ce cas, à quoi sert le SELECT DISTINCT
?
Sans celui-ci on obtiendrait quelque chose comme le tableau ci-après (les enregistrements étant regroupés par client et par facture) :
f.fkClient.num | f.fkClient.nom | f.num | lf.qte |
---|---|---|---|
1 | A | 1 | 6 |
1 | A | 2 | 7 |
1 | A | 3 | 6 |
2 | B | 4 | 12 |
2 | B | 5 | 6 |
... | ... | ... |
Comme on souhaite ne projeter que le numéro et le nom du client, toujours sans le DISTINCT, on obtiendrait :
f.fkClient.num | f.fkClient.nom |
---|---|
1 | A |
1 | A |
1 | A |
2 | B |
2 | B |
... | ... |
Le DISTINCT permet donc bien de supprimer les doublons :
f.fkClient.num | f.fkClient.nom |
---|---|
1 | A |
2 | B |
... | ... |
Question
Quelle aurait été une solution plus élégante à la question précédente ? Proposez une implémentation de cette solution en RO et une nouvelle requête utilisant cette solution.
Solution
Il aurait été plus judicieux d'implémenter une méthode quantite() dans la table des factures. On ajoute MEMBER FUNCTION quantite RETURN NUMBER en fin de déclaration de type.
Mise à jour du type typFacture
ALTER TYPE typFacture ADD MEMBER FUNCTION quantite RETURN NUMBER CASCADE;
Ajout du corps de la méthode quantite()
CREATE OR REPLACE TYPE BODY typFacture AS
MEMBER FUNCTION total RETURN NUMBER
IS
vTotal NUMBER;
BEGIN
SELECT SUM(lf.qte*lf.fkproduit.prix) INTO vTotal
FROM Facture f, TABLE(f.lignes_facture) lf
WHERE f.num = SELF.num;
RETURN vTotal;
END total;
MEMBER FUNCTION quantite RETURN NUMBER IS
vQuantite NUMBER;
BEGIN
SELECT SUM(lf.qte) INTO vQuantite
FROM Facture f, TABLE(f.Lignes_facture) lf
WHERE f.num = self.num;
RETURN vQuantite;
END quantite;
END;
La requête d'exploitation
SELECT DISTINCT f.fkClient.num AS numero, f.fkClient.nom AS nom
FROM Facture f
WHERE f.quantite() > 5;