[[04_Requêtes sur 2 tables]] # Méthodologie : Déterminer et Construire les Requêtes ## Introduction Écrire une requête SQL sans réflexion préalable est une erreur. ***Le SQL est la traduction technique d’un raisonnement logique.*** >[!tip] Avant d’écrire du code, il faut : > >1. Comprendre ce que représente un enregistrement attendu. >2. Identifier les données nécessaires. >3. Vérifier si ces données existent. >4. Déterminer si certaines doivent être calculées. >5. Organiser les requêtes dans le bon ordre. --- ## Objectifs À la fin de ce chapitre, vous serez capable de : - Analyser une demande. - Identifier les tables nécessaires. - Vérifier si les données existent. - Déterminer si des données doivent être calculées. - Découper un problème en plusieurs requêtes. - Construire la requête finale proprement. --- ## 1. Étape 1 — Comprendre la demande ### 1.1 Ouvrir et comprendre le schéma relationnel Toujours commencer par : - Identifier les tables - Identifier les clés primaires - Identifier les clés étrangères - Comprendre les relations Si vous ne regardez pas le schéma, vous travaillez au hasard. --- ### 1.2 Déterminer ce que représente un enregistrement Il est important de comprendre ce que vous voulez avoir au final >[!tip] Question obligatoire : > > Une enregistrement du résultat correspond à quoi ? > >Exemples : >- Un client ? >- Une commande ? >- Un client avec son nombre de commandes ? >- Une ville avec son chiffre d’affaires ? >[!warning] Puis-je passer à la suite ? >Si ce point n’est pas clair, vous ne pouvez pas écrire la requête. --- ## 2. Étape 2 — Les données existent-elles ? Maintenant que je sais ce que je veux, je dois savoir si je vais pouvoir résoudre le problème : les données sont-elles dans la base de données ou puis-je les calculer à l'aide de ces données ? ### 2.1 Données déjà présentes Si les données existent telles quelles, une simple sélection suffit. >[!tips] Exemples > >- nom_client → table `Clients` >- date_commande → table `Commandes` >- montant_total → table `Commandes` --- ### 2.2 Données à calculer Si je ne trouve pas la donnée dans un champ d'une table, je vais chercher à savoir si je peux la calculer à l'aide de données bien présentes dans la base de données. >[!tip] Exemples >- Nombre de commandes → `COUNT` >- Total des ventes → `SUM` >- Moyenne → `AVG` >[!tip] Fonctions d'agrégat >Généralement, Une donnée calculée implique : >- `GROUP BY` >- éventuellement `HAVING` --- ## 3. Étape 3 — Combien de requêtes ? ### Cas simple Une seule requête suffit si : - Toutes les données sont accessibles directement - Les calculs peuvent être faits dans la même requête --- ### Cas complexe Plusieurs requêtes sont nécessaires si : - Une table nécessaire est le résultat d’un calcul - Une requête doit servir d’entrée à une autre - La logique est plus claire en plusieurs étapes Si une table est le résultat d’une requête, on applique la méthode à cette requête intermédiaire. --- ## 4. Étape 4 — Préparer la requête Toujours réfléchir dans cet ordre : 1. `FROM` — Quelles tables ? 2. `WHERE` — Quels filtres ? 3. `GROUP BY` — Faut-il regrouper ? 4. `HAVING` — Faut-il filtrer les groupes ? 5. `ORDER BY` — Faut-il trier ? 6. `SELECT` — Que veut-on afficher ? Attention : ordre de réflexion ≠ ordre d’écriture SQL. Pour vous aider, nous vous proposons de vous aider du schéma ci-dessous : ![[Preparer_sa_requete.pdf]] Une fois rempli et fait pour chaque requête, ce schéma vous permettra décrire rapidement vos requête. >[!tip] Corrections des ateliers > Vous verrez que nous utilisons ce schéma pour la correction des exercices. ## 5. Exemple d'une demande amenant à une requête complexe En utilisant la description des deux tables suivantes, on nous demande la liste des clients dont le chiffre d’affaires total est supérieur à la moyenne du chiffre d’affaires de tous les clients. #### La table *Clients* | id_client | nom_client | ville_client | date_inscription | | --------- | ---------- | ------------ | ---------------- | | 1 | Martin | Paris | 2022-03-15 | | 2 | Dupont | Lyon | 2021-11-02 | | 3 | Bernard | Marseille | 2023-01-20 | | 4 | Petit | Lille | 2022-07-08 | | 5 | Robert | Bordeaux | 2023-05-12 | #### La table *Commandes* | id_commande | id_client | date_commande | montant_total | | ----------- | --------- | ------------- | ------------- | | 101 | 1 | 2023-01-10 | 250.00 | | 102 | 1 | 2023-02-18 | 120.00 | | 103 | 2 | 2023-03-05 | 560.00 | | 104 | 2 | 2023-04-22 | 80.00 | | 105 | 2 | 2023-06-01 | 310.00 | | 106 | 3 | 2023-07-14 | 150.00 | | 107 | 4 | 2023-08-03 | 400.00 | ### Ai-je les données pour répondre à cette demande ? Dans les tables, je ne trouve ni le chiffre d'affaires total des clients, ni la moyenne du chiffre d’affaires de tous les clients. Puis-je les calculer ? 1- Le chiffre d'affaire total pour un client peut se calculer en faisant la somme des *montant_total* 2- La moyenne du chiffre d’affaires de tous les clients, peut se calculer après avoir fait le calcul du point 1- je peux donc en conclure que je peux répondre à la demande. ### Combien de requête me faudra-t-il ? 1. Il me faut ***une première requête*** qui calcule **les chiffres d'affaires par client** et les compare à **la moyenne des chiffres d'affaires**. cette requête aura en entrée les tables *Clients* et *Commandes* et une deuxième requête. 2. En effet, La moyenne des chiffres d'affaires n'étant pas présente dans la base de données, je dois faire ***une deuxième requête*** qui retourne cette valeur. 3. En entrée de cette requête, il faut avoir le chiffre d'affaire de chaque client que l'on va obtenir à l'aide d'***une troisième requête***. Ce qui donne le diagramme suivant : ```mermaid graph TD A@{ shape: text, label: "Clients" }-->C["3ème Requête"] B@{ shape: text, label: "Commandes" }-->C C-->D@{ shape: text, label: "Chiffre d'affaires par client" } D-->E["2ème Requête"] E-->F@{ shape: text, label: "Moyenne des Chiffre d'affaires par client" } G@{ shape: text, label: "Clients" }-->I["1ère Requête"] H@{ shape: text, label: "Commandes" }-->I F-->I I-->J@{ shape: text, label: "Clients dont le chiffre d'affaires est supérieur à la moyenne" } ``` ### Préparation des requêtes Avant de les écrire, nous vous conseillons de préparer chaque requête pour : 1. Bien comprendre ce que vous faites 2. Ne pas passer trop de temps à taper du code SQL #### Préparation de la 3ème requête ![[cours01.png|500]] #### Préparation de la 2ème requête ![[cours02.png|500]] #### Préparation de la 1ère requête ![[cours03.png|500]] ### Requête finale ``` SQL SELECT -- Troisième requête : clients dont le CA > CA moyen C.id_client, C.nom_client, SUM(Co.montant_total) AS chiffre_affaires FROM Clients C INNER JOIN Commandes Co ON C.id_client = Co.id_client , ( -- Deuxième requête : moyenne du chiffre d’affaires par client SELECT AVG(ca_client) AS moyenne_ca FROM ( -- Première requête : chiffres d'affaires par client SELECT SUM(Co2.montant_total) AS ca_client FROM Clients C2 INNER JOIN Commandes Co2 ON C2.id_client = Co2.id_client GROUP BY C2.id_client ) AS t ) AS m GROUP BY C.id_client, C.nom_client, m.moyenne_ca HAVING SUM(Co.montant_total) > m.moyenne_ca; ``` Dans le chapitre d'après, nous allons généraliser la lecture du FROM avec plusieurs tables : [[06_Généralisation_Requête sur n tables]]