Vérifier le résultat d'une requête
Une requête peut s'exécuter sans erreur tout en répondant à une autre question. La difficulté est de repérer cet écart avant que le chiffre arrive dans une synthèse.
Bloc du titre : BC01, l'intégrité des données, et BC02, écarter les valeurs anormales. C'est ce qui sépare un chiffre que tu peux défendre devant un jury d'un chiffre recopié.
Les trois premiers cas ci-dessous sont sur les données du TP. Chacun produit un résultat propre, sans erreur, sans avertissement. Chacun répond à côté. Le quatrième porte sur la phrase écrite sous la requête.
1. L'alias qui dit le contraire de la requête
Un alias est le nom que tu donnes à une colonne du résultat, avec AS. Prends
la table products et compte ses poids manquants.
SELECT COUNT(product_weight_g) AS poids_manquants
FROM products;Avant de l'exécuter : products contient 32 951 lignes. À ton avis, l'ordre de
grandeur de la réponse, c'est la dizaine, le millier, ou les trente mille ?
Exécute.
Elle renvoie 32 949.
COUNT(colonne) compte les valeurs présentes, pas les valeurs absentes. Le nom
de la colonne dit « manquants ». La requête compte l'inverse. PostgreSQL n'a
aucune raison de protester : l'alias est une étiquette, il n'engage rien.
Le compte juste :
SELECT COUNT(*) FILTER (WHERE product_weight_g IS NULL) AS poids_manquants
FROM products;2. Deux lignes sur 32 951.
Entre 32 949 et 2, la requête a répondu à la question inverse. L'écart ne se voit que si tu t'es donné un ordre de grandeur avant de lancer la requête. C'est le rôle de la prédiction : rendre l'absurde visible.
COUNT(*) - COUNT(colonne) vaut quoi ?
Trois écritures équivalentes, à connaître :
COUNT(*) FILTER (WHERE x IS NULL),COUNT(*) - COUNT(x), etSUM(CASE WHEN x IS NULL THEN 1 ELSE 0 END). La première dit ce qu'elle fait.
2. La jointure qui change la maille
SELECT COUNT(*) AS lignes_apres_jointure,
COUNT(DISTINCT s.seller_id) AS vendeurs_distincts
FROM sellers s
JOIN order_items i ON i.seller_id = s.seller_id
WHERE s.seller_state IN ('BA', 'CE');Avant de l'exécuter, prédis lequel des deux comptes sera le plus grand. Un vendeur peut apparaître sur plusieurs lignes d'articles : la jointureRapprocher deux tables sur une colonne commune, pour lire ensemble des informations qui sont stockées séparément. conserve ces correspondances, elle ne les fusionne pas.
Vérifie-le toi-même :
SELECT s.seller_id, COUNT(*) AS lignes_articles
FROM sellers s
JOIN order_items i ON i.seller_id = s.seller_id
WHERE s.seller_state IN ('BA', 'CE')
GROUP BY s.seller_id
ORDER BY lignes_articles DESC
LIMIT 5;Le résultat montre pourquoi le nombre de lignes jointes peut dépasser le nombre
de vendeurs. Pour compter des vendeurs, utilise COUNT(DISTINCT s.seller_id).
Pour compter des lignes d'articles, utilise COUNT(*).
La règle : chaque fois que tu écris un JOIN, compare le nombre de lignes
avant et après. S'il change, tu dois pouvoir dire pourquoi. Sinon, tu as perdu
des données sans le savoir.
Après un JOIN, tu as plus de lignes qu'avant. Qu'est-ce que ça peut indiquer ?
Deux pièges du même genre :
- Une jointure peut aussi ajouter des lignes. Joins
ordersàorder_paymentset compte : une commande avec plusieurs paiements apparaît plusieurs fois. C'est la bonne maille pour additionner les paiements ; cela surcompte une mesure définie une fois par commande si tu ne regroupes pas avant. WHERE x <> 'valeur'écarte aussi les lignes oùxestNULL. Une comparaison avecNULLne vaut ni vrai ni faux.
3. Le tri sur un identifiant
Pour trouver le premier avis déposé, on peut trier et prendre la première ligne.
SELECT review_creation_date
FROM order_reviews
ORDER BY review_id ASC
LIMIT 1;Elle renvoie 2018-03-20.
SELECT MIN(review_creation_date) FROM order_reviews;2016-10-02.
Près de dix-huit mois d'écart. review_id est un identifiant, pas une date. Il
ne porte aucune information de temps. Trier dessus donne un ordre déterministe
et sans signification.
Le même piège existe sur order_id, customer_id, product_id : ce sont des
chaînes de caractères tirées au hasard. Pour ordonner dans le temps, il faut une
colonne de date.
4. L'explication plausible qu'on n'a pas testée
Les trois premiers cas portent sur une requête. Celui-ci porte sur la phrase écrite en dessous.
Tu repères des dimensions manquantes dans products. Une explication vient :
ce seraient seulement des fiches sans photo. C'est plausible. Une requête
tranche.
SELECT product_photos_qty AS photos,
COUNT(*) AS produits,
COUNT(*) FILTER (WHERE product_weight_g IS NULL) AS poids_absent,
COUNT(*) FILTER (WHERE product_length_cm IS NULL) AS longueur_absente
FROM products
GROUP BY product_photos_qty
ORDER BY photos NULLS FIRST;Regarde les groupes. Si l'explication « seules les fiches sans photo ont des dimensions manquantes » couvrait toutes les lignes, les autres groupes seraient à zéro dans les deux dernières colonnes. La requête permet de confirmer ou de réfuter cette explication.
Si une ligne avec photo porte encore une absence, l'explication est réfutée. Si elle n'en porte aucune, elle est confirmée sur ce jeu de données, avec cette requête comme preuve.
La règle : une explication qui se vérifie en une requête, et qu'on n'a pas lancée, est une supposition. Même quand elle est raisonnable. Dans une note de nettoyage, ce qui est évalué est de pouvoir montrer la requête qui confirme l'explication.
5. Quatre questions à se poser à chaque requête
Écris les réponses à ces questions dans ton fichier avant de valider le résultat.
- Quel ordre de grandeur j'attends ? Écris-le avant d'exécuter. Un résultat qui tombe à côté se voit alors tout de suite.
- Mes alias décrivent-ils ce que la requête calcule ? Une colonne nommée
manquantsqui compte les présents est un piège que tu te tends à toi-même. Tu le retrouveras dans ta synthèse. - Combien de lignes en entrée, combien en sortie ? Après un
JOIN, après unWHERE, après unGROUP BY. Si le nombre change et que tu ne sais pas pourquoi, arrête-toi là. - Mon explication, je l'ai testée ou supposée ? Si une requête peut la confirmer, écris-la et lance-la avant de conclure.
Cette vérification ne dépend pas de qui a écrit la requête. Que tu l'aies tapée toi-même ou qu'un assistant te l'ait proposée, c'est toi qui signes le chiffre.
6. Où ça te sert dans le TP
- Partie 1, tu comptes des valeurs manquantes : c'est le cas 1.
- Partie 2, tu calcules un chiffre d'affaires en joignant
orders,order_itemsetorder_payments: le cas 2 t'attend à chaque jointure. - Partie 2, question 4, un top 10 : le cas 3 t'attend au premier
ORDER BY, dès que la colonne de tri n'est pas celle que tu crois. - Le livrable de la partie 1 est une note d'explications : le cas 4 y est à chaque paragraphe.
Dans la synthèse d'une page, tu devras défendre tes chiffres devant quelqu'un qui n'a pas vu tes requêtes. Ces quatre questions sont celles qu'on te posera.