{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "introduction",
   "metadata": {},
   "source": [
    "# TP SQL — la base `education.db`\n",
    "\n",
    "Écoles, collèges, lycées, spécialités et communes de France : la base\n",
    "`education.db` est décrite en détail dans `README_bases.md`. Ce qu'il faut\n",
    "savoir pour ce TP :\n",
    "\n",
    "- **aucune valeur `NULL`** ; dans les tables d'effectifs, l'absence de ligne signifie un effectif nul ;\n",
    "- les **codes** (`code_insee`, `code_commune`, `dep_code`, `uai`…) sont des **chaînes de caractères** : on écrit `dep_code = '78'`, avec des apostrophes ;\n",
    "- les établissements sont **datés** : la clé primaire de `ecoles`, `colleges` et `lycees` est le couple `(uai, rentree)`.\n",
    "\n",
    "**Rappels hors programme** : `NULL`, `LEFT JOIN`, `WITH`, `IN`/`NOT IN`, `EXISTS`, `GROUP_CONCAT`.\n",
    "\n",
    "Tout ce TP se traite avec `SELECT … FROM … JOIN … ON … WHERE … GROUP BY … HAVING … ORDER BY … LIMIT/OFFSET`,\n",
    "les sous-requêtes et `UNION`/`INTERSECT`/`EXCEPT`."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "chargement-base",
   "metadata": {},
   "source": [
    "## Chargement de la base"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d5b74ad",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "name\n",
      "------------------\n",
      "communes\n",
      "ecoles\n",
      "colleges\n",
      "effectifs_colleges\n",
      "lycees\n",
      "effectifs_lycees\n",
      "specialites\n",
      "combinaisons\n",
      "cpge\n"
     ]
    }
   ],
   "source": [
    "from sql_fonctions import GestionnaireSQL\n",
    "\n",
    "db = GestionnaireSQL(\"education.db\")\n",
    "db.liste_tables()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d94eb764",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "communes : ['code_insee', 'nom_standard', 'nom_sans_pronom', 'nom_a', 'nom_de', 'nom_sans_accent', 'nom_majuscule', 'reg_code', 'reg_nom', 'dep_code', 'dep_nom', 'epci_code', 'epci_nom', 'code_postal', 'academie_code', 'academie_nom', 'population', 'superficie_km2', 'altitude_moyenne', 'altitude_min', 'altitude_max', 'latitude_mairie', 'longitude_mairie', 'latitude_centre', 'longitude_centre', 'grille_densite', 'grille_densite_texte', 'gentile', 'url_wikipedia']\n",
      "ecoles : ['uai', 'rentree', 'denomination', 'patronyme', 'secteur', 'code_commune', 'rep', 'rep_plus', 'nb_classes', 'pre_elementaire', 'elementaire', 'ulis']\n",
      "colleges : ['uai', 'rentree', 'denomination', 'patronyme', 'secteur', 'code_commune', 'rep', 'rep_plus']\n",
      "effectifs_colleges : ['uai', 'rentree', 'niveau', 'filles', 'garcons']\n",
      "lycees : ['uai', 'rentree', 'denomination', 'patronyme', 'secteur', 'code_commune']\n",
      "effectifs_lycees : ['uai', 'rentree', 'niveau', 'serie', 'filles', 'garcons']\n",
      "specialites : ['uai', 'rentree', 'niveau', 'code_specialite', 'specialite', 'filles', 'garcons']\n",
      "cpge : ['rentree', 'ministere', 'filiere', 'annee_etude', 'garcons_public', 'filles_public', 'garcons_prive', 'filles_prive']\n"
     ]
    }
   ],
   "source": [
    "# Les schémas des tables utilisées dans ce TP.\n",
    "for table in [\"communes\", \"ecoles\", \"colleges\", \"effectifs_colleges\",\n",
    "              \"lycees\", \"effectifs_lycees\", \"specialites\", \"cpge\"]:\n",
    "    print(f\"{table} : {db.schema('SELECT * FROM ' + table)}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "utilisation-requetes",
   "metadata": {},
   "source": [
    "### Exécuter une requête dans ce TP\n",
    "\n",
    "Placer ce notebook, `education.db` et `sql_fonctions.py` dans le même dossier, puis exécuter les deux cellules de chargement ci-dessus avec **Maj + Entrée**. Dans une cellule de code, écrire une requête SQL entre les triples guillemets de `db.requete(\"\"\"…\"\"\")`, puis exécuter la cellule : les noms des colonnes et les lignes du résultat s'affichent en dessous. Les triples guillemets permettent d'écrire la requête sur plusieurs lignes ; les valeurs textuelles SQL restent entre apostrophes. Par exemple :\n",
    "\n",
    "```python\n",
    "db.requete(\"\"\"\n",
    "SELECT nom_standard\n",
    "FROM communes\n",
    "LIMIT 5\n",
    "\"\"\")\n",
    "```\n",
    "\n",
    "Modifier la requête et réexécuter la cellule pour essayer une autre solution. Pour la partie graphique, `db.liste(\"\"\"…\"\"\")` renvoie une liste de tuples à conserver dans une variable, tandis que `db.schema(\"\"\"…\"\"\")` renvoie les noms des colonnes. Après un redémarrage du noyau, réexécuter les cellules de chargement."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "25b69163",
   "metadata": {},
   "source": [
    "## 1. Lire le schéma\n",
    "\n",
    "**Question 1**. Sans écrire de requête :\n",
    "\n",
    "1. Quelle est la clé primaire de `communes` ? Celle de `lycees` ? Pourquoi `uai` seul ne suffit-il pas ?\n",
    "2. Quelle colonne de `lycees` est une clé étrangère, et vers quelle colonne de quelle table ?\n",
    "3. Donner le type d'association ($1-1$, $1-*$ ou $*-*$) entre : `communes` et `lycees` ; `lycees` et `effectifs_lycees` ; les lycées et les spécialités."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "reponse-cf0daa31",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "2cff0658",
   "metadata": {},
   "source": [
    "## 2. Une seule table\n",
    "\n",
    "**Question 2** *(projection, sélection, tri)*. Le nom et la population des communes des Yvelines\n",
    "(`dep_code = '78'`) de plus de 20 000 habitants, par population décroissante."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-4a265f76",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "3b8f5a34",
   "metadata": {},
   "source": [
    "**Question 3** *(`DISTINCT`)*.\n",
    "\n",
    "1. Comparer le nombre de lignes de `colleges` et son nombre d'établissements distincts. Expliquer l'écart.\n",
    "2. Combien de communes distinctes comptent au moins un collège REP+ à la rentrée 2025 ?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-06a5fa37",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "4cabcd8a",
   "metadata": {},
   "source": [
    "**Question 4** *(`ORDER BY`, `LIMIT`, `OFFSET`)*. Les trois communes les plus peuplées de\n",
    "France, puis les communes des rangs 4 à 10 (nom et population)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-177d4b6f",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "d198f8a6",
   "metadata": {},
   "source": [
    "**Question 5** *(renommage `AS`)*. Les dix communes les plus denses parmi celles de plus de\n",
    "10 000 habitants (nom et densité en habitants/km²)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-d8ff2af4",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "9b6708bb",
   "metadata": {},
   "source": [
    "### Agrégats\n",
    "\n",
    "**Question 6** *(agrégats simples)*. En une seule requête : le nombre de communes des Yvelines,\n",
    "leur population totale, leur superficie totale et l'altitude du plus haut sommet du département."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-5d8bec6c",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "2ef5a19f",
   "metadata": {},
   "source": [
    "**Question 7** *(`GROUP BY`)*. Le nombre de communes et la population totale de chaque région,\n",
    "par population décroissante (nom de région, nombre de communes, population de la région)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-a18d403d",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "84093f1f",
   "metadata": {},
   "source": [
    "**Question 8** *(`WHERE` et `HAVING`)*. Les académies comptant au moins cinq communes de plus de\n",
    "50 000 habitants, avec ce nombre, par ordre décroissant."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-463060b0",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "ac47842b",
   "metadata": {},
   "source": [
    "**Question 9** *(division entière !)*. La proportion de filles en terminale générale (série `G`)\n",
    "en France à la rentrée 2025."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-3f46d35c",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "7cc1eb50",
   "metadata": {},
   "source": [
    "### Sous-requêtes\n",
    "\n",
    "**Question 10** *(sous-requête scalaire)*. La commune la plus peuplée des Yvelines, de deux\n",
    "façons : avec `ORDER BY … LIMIT 1`, puis avec une sous-requête scalaire. Quelle version garde\n",
    "les ex æquo ? Pourquoi `SELECT nom_standard, MAX(population)` serait-il incorrect ?\n",
    "\n",
    "On affichera (nom, population)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-12de811d",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "3635911e",
   "metadata": {},
   "source": [
    "**Question 11** *(rang)*. Le rang de Versailles au classement des communes françaises par\n",
    "population décroissante."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-7ebdd7f7",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "7f2891d1",
   "metadata": {},
   "source": [
    "**Question 12** *(agrégat d'agrégat)*. Le nombre moyen d'écoles par commune à la rentrée 2025\n",
    "(parmi les communes qui en ont au moins une)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-9adfee1c",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "b66c299a",
   "metadata": {},
   "source": [
    "**Question 13** *(compter des groupes)*. Dans un département, appelons *doublon* un ensemble\n",
    "de communes ayant exactement la même population. Les départements comptant au moins cent\n",
    "doublons, avec ce nombre, par nombre décroissant."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-d556be75",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "deed944e",
   "metadata": {},
   "source": [
    "## 3. Jointures\n",
    "\n",
    "Toute cette partie se joue dans l'univers des lycées, avec des tables introduites une à une :\n",
    "d'abord le couple `lycees`–`communes`, puis `effectifs_lycees`, et enfin la table d'association\n",
    "`specialites`.\n",
    "\n",
    "### 3.1 Un premier couple : `lycees` et `communes`\n",
    "\n",
    "**Question 14** *(jointure simple)*. La dénomination, le patronyme et le secteur des lycées de\n",
    "Versailles à la rentrée 2025."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-83e68a5b",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "f2341144",
   "metadata": {},
   "source": [
    "**Question 15** *(désigner par la clé, pas par le nom)*. Combien la commune nommée Saint-Denis\n",
    "compte-t-elle de lycées à la rentrée 2025 ? La réponse obtenue est-elle correcte ?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-8cc90bad",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "05d32338",
   "metadata": {},
   "source": [
    "### 3.2 Un deuxième couple : `lycees` et `effectifs_lycees`\n",
    "\n",
    "**Question 16** *(condition de jointure composée)*. Le patronyme et l'effectif de terminale G\n",
    "des lycées de Versailles à la rentrée 2025, par effectif décroissant. Le code INSEE de\n",
    "Versailles, lu dans `communes` à la question 14, est `'78646'`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-c2d5dd5b",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "18df66d2",
   "metadata": {},
   "source": [
    "**Question 17** *(joindre avant d'agréger)*. Le plus grand effectif de terminale G d'un lycée\n",
    "privé à la rentrée 2025."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-8c7badf4",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "8b34d3e3",
   "metadata": {},
   "source": [
    "**Question 18** *(portée d'une sous-requête scalaire)*. Le ou les lycées privés atteignant ce\n",
    "record en 2025 (patronyme, effectif). Que renvoie la requête si la sous-requête calcule le maximum sur tous les lycées ?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-2badaa46",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "c7a9fd76",
   "metadata": {},
   "source": [
    "### 3.3 La même table des deux côtés : autojointures\n",
    "\n",
    "**Question 19** *(autojointure)*. Les paires de lycées distincts de Versailles à la rentrée\n",
    "2025. Combien de lignes obtiendrait-on avec `<>` au lieu de `<` ? Et sans aucune condition\n",
    "sur les `uai` ?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-56e7b4b9",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "3399d2ac",
   "metadata": {},
   "source": [
    "**Question 20** *(autojointure temporelle)*. Pour chaque lycée de Versailles, l'effectif de\n",
    "terminale G à la rentrée 2019 et à la rentrée 2025, et la variation entre les deux, par\n",
    "variation décroissante."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-370aed86",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "725b2ae1",
   "metadata": {},
   "source": [
    "### 3.4 Trois tables et plus\n",
    "\n",
    "**Question 21** *(jointure triple, agrégat)*. Les dix académies dont l'effectif total de\n",
    "terminale G est le plus élevé à la rentrée 2025 (nom, effectif)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-22d6b959",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "f69b75f5",
   "metadata": {},
   "source": [
    "**Question 22** *(maximum par groupe)*. Pour chaque académie, le lycée dont l'effectif de\n",
    "terminale G est le plus élevé à la rentrée 2025 (académie, patronyme, effectif), par effectif\n",
    "décroissant. Pourquoi la sous-requête scalaire de la question 18 ne suffit-elle plus ici ?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-2d8b1a8d",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "ab8d62a2",
   "metadata": {},
   "source": [
    "**Question 23** *(deux jointures triples)*. Les dix académies où la proportion d'élèves de\n",
    "terminale inscrits en voie générale (série `G`) est la plus élevée à la rentrée 2025\n",
    "(nom, proportion)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-e27aeaf8",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "18e373d2",
   "metadata": {},
   "source": [
    "**Question 24** *(table d'association : traduire un « et »)*. Les lycées de l'académie de\n",
    "Versailles proposant, en terminale à la rentrée 2025, à la fois « Numérique et sciences\n",
    "informatiques » et « Arts plastiques » (patronyme du lycée, nom de la commune). Pourquoi la condition\n",
    "`specialite = 'Numérique et sciences informatiques' AND specialite = 'Arts plastiques'`\n",
    "renvoie-t-elle une table vide ?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-67c994e1",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "2f733f3b",
   "metadata": {},
   "source": [
    "## 4. Ensembles et antijointure\n",
    "\n",
    "**Question 25** *(`INTERSECT`)*. Les codes INSEE des communes des Yvelines ayant au moins un\n",
    "lycée à la rentrée 2025."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-7bff62b8",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "b193d827",
   "metadata": {},
   "source": [
    "**Question 26** *(`EXCEPT` et antijointure)*.\n",
    "\n",
    "1. Combien de communes de plus de 10 000 habitants n'ont aucun lycée à la rentrée 2025 ?\n",
    "2. Donner le nom, le département et la population des dix plus peuplées d'entre elles."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-1beb7b84",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "d62f86ea",
   "metadata": {},
   "source": [
    "**Question 27** *(distance)*. La commune des Yvelines, autre que Versailles, dont le centre est\n",
    "le plus proche de celui de Versailles (au sens de la distance euclidienne sur les coordonnées\n",
    "`latitude_centre`, `longitude_centre`)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-536eb612",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "88ae4dff",
   "metadata": {},
   "source": [
    "## 5. Synthèse et compléments\n",
    "\n",
    "**Question 28** *(la requête complète)*. Pour chaque académie, le nombre de lycées publics de la\n",
    "rentrée 2025 situés dans une commune de moins de 20 000 habitants ; ne garder que les académies\n",
    "en comptant au moins vingt, par nombre décroissant de lycées."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-8bd7d6d8",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "5db5077a",
   "metadata": {},
   "source": [
    "**Question 29** *(bonus, une table pour finir)*. Pour chaque rentrée, le nombre total d'étudiants\n",
    "en CPGE et la proportion de filles. Attention à la division…"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-048fdf0a",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "07aa9648",
   "metadata": {},
   "source": [
    "**Question 30** *(bonus, retour sur la question 15)*. Plusieurs communes peuvent porter\n",
    "le même nom. On s'intéresse ici aux couples de communes homonymes.\n",
    "\n",
    "1. Combien y a-t-il de couples de communes distinctes portant le même nom ?\n",
    "2. En donner les vingt premiers par ordre alphabétique (nom, et les deux départements)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-758d097a",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "utilisation-donnees",
   "metadata": {},
   "source": [
    "## 6. Utilisation des données *(bonus)*\n",
    "\n",
    "Cette partie ne sera pas traitée en TP. Elle montre ce que l'on fait des résultats d'une\n",
    "requête une fois revenu dans Python : le SQL fait le calcul, matplotlib le donne à voir."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "94519995",
   "metadata": {},
   "source": [
    "### Importation de matplotlib et de la fonction $\\log_{10}$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f65ba802",
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from math import log10"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2ca71fee",
   "metadata": {},
   "source": [
    "On écrit les requêtes en langage SQL comme précédemment, mais on utilise la fonction\n",
    "`db.liste` pour récupérer la liste des données demandées (sans le schéma de la table)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2838c13a",
   "metadata": {},
   "source": [
    "### Création d'une carte"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e718e56e",
   "metadata": {},
   "source": [
    "**Question 31** *(du SQL au graphique)*\n",
    "\n",
    "1. Récupérer dans une liste nommée `V` la longitude et la latitude du centre de chaque commune\n",
    "de France métropolitaine, ainsi que sa densité (hab/km²).\n",
    "2. Stocker dans `x` la liste des longitudes, dans `y` celle des latitudes et dans `L_d` les\n",
    "images des densités par $t \\mapsto \\log_{10}(t+1)$.\n",
    "3. À l'aide d'une requête SQL, récupérer dans `D` la densité maximale des communes de France\n",
    "métropolitaine."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-ba0771e7",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "4ab2674b",
   "metadata": {},
   "source": [
    "Une fois `x`, `y`, `L_d` et `D` calculés, exécuter la cellule suivante pour tracer la carte."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "03663a5e",
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots()\n",
    "\n",
    "# Tracé\n",
    "points = ax.scatter(x, y, c=L_d, cmap=\"YlOrRd\", vmin=0, vmax=log10(D+1), marker=\"s\", s=0.75)\n",
    "\n",
    "# Création de la légende\n",
    "cbar = fig.colorbar(points, label=\"Densité (hab/km²)\")\n",
    "\n",
    "# Graduations entières de 0 à la valeur maximale possible\n",
    "ticks = list(range(0, int(log10(D+1)) + 1))\n",
    "\n",
    "# Étiquettes en puissances de 10 correspondantes\n",
    "labels = [f\"$10^{k}$\" for k in ticks]\n",
    "\n",
    "cbar.set_ticks(ticks)\n",
    "cbar.set_ticklabels(labels)\n",
    "\n",
    "ax.set_axis_off()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "39a2a00c",
   "metadata": {},
   "source": [
    "4. Récupérer dans une liste nommée `G` les centres de gravité démographiques (barycentres des\n",
    "centres des communes, pondérés par leur population) des départements de France métropolitaine\n",
    "(`dep_code` strictement inférieur à `'96'` : c'est une chaîne de caractères)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "reponse-5e1f8ed4",
   "metadata": {
    "tags": [
     "reponse"
    ]
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "51f0b491",
   "metadata": {},
   "source": [
    "Une fois `G` calculée, extraire les longitudes dans `xG` et les latitudes dans `yG`, puis exécuter la cellule suivante pour ajouter ces points à la carte."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "082c0a6c",
   "metadata": {},
   "outputs": [],
   "source": [
    "ax.scatter(xG, yG, marker=\"s\", s=0.75,c='k')\n",
    "fig\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
