Apprendre SQL : Lire dans sa BDD (SELECT)

Récupérez les données de votre base de données avec des requêtes SQL.

Icône de calendrier
Débutant
7 chapitres

Dans un CRUD, on retrouve également une opération dite de lecture. Pour lire des données, on effectuera des requêtes de sélection.

Sélection

Pour récupérer des données stockées en BDD, on utilise les mots-clés SELECT et FROM.

  • SELECT permet de spécifier quelles colonnes récupérer au sein de la table.
  • FROM permet de spécifier dans quelle table effectuer la sélection.

Cette commande retourne des enregistrements dans un tableau de résultat.

copié !
-- Récupération d'une colonne
SELECT colonne FROM nom_table;
copié !
-- Récupération de plusieurs colonnes
SELECT colonne_1, colonne_2 FROM nom_table;
copié !
-- Récupération de toutes les colonnes
SELECT * FROM nom_table;
📌 En pratique

Considérons la table articles, stockant les articles d’un blog :

idtitrecontenuauteur
1Maitriser les variables CSSLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Sébastien Chopin
2Netlify VS Vercel : quelle est la meilleure solution d’hébergement de sites statiques ?Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.Evan You
3Tout savoir sur les balises sémantiques en HTML.Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.Sébastien Chopin

La requête suivante permet de récupérer tous les titres d’articles :

copié !
SELECT titre FROM articles;
titre
Maitriser les variables CSS
Netlify VS Vercel : quelle est la meilleure solution d’hébergement de sites statiques ?
Tout savoir sur les balises sémantiques en HTML.

L’utilisation de la commande SELECT récupère l’ensemble des enregistrements d’une table. En revanche, cette commande peut potentiellement afficher des lignes en double. Pour éviter des doublons dans les résultats il faudra alors ajouter DISTINCT après le mot SELECT.

copié !
SELECT DISTINCT colonne
FROM nom_table;
📌 En pratique

Considérons la table articles, stockant les articles d’un blog :

idtitrecontenuauteur
1Maîtriser les variables CSSLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Sébastien Chopin
2Netlify VS Vercel : quelle est la meilleure solution d’hébergement de sites statiques ?Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.Evan You
3Tout savoir sur les balises sémantiques en HTML.Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.Sébastien Chopin

La requête suivante permet de récupérer la liste des auteurs (sans doublons) :

copié !
SELECT DISTINCT auteur FROM articles;
auteur
Sébastien Chopin
Evan You

Si ces commandes s’avèrent très utiles lorsqu’il s’agit de travailler sur un jeu de données complet, bien souvent, nous ne souhaitons en récupérer qu’une partie. Pour cela, nous aurons la possibilité de filtrer les résultats avec la clause WHERE, abordée plus tard dans ce cours.

Calculs

Parfois, il est intéressant d’effectuer des calculs sur un ensemble de données d’une colonne. Nous aurons alors besoin de fonctions d’agrégations statistiques.

copié !
SELECT FONCTION(colonne) FROM nom_table;

Il existe plusieurs fonctions d’agrégations statistiques qui s’appliquent sur un ensemble d’enregistrements. Les principales sont les suivantes :

  • SUM() pour calculer la somme de plusieurs lignes.
  • AVG() pour calculer la moyenne de plusieurs lignes.
  • COUNT() pour compter le nombre de lignes concernées.
  • MAX() pour récupérer la plus grande valeur.
  • MIN() pour récupérer la plus petite valeur.

Faire appel à une fonction d’agrégation statistique a pour effet de créer une nouvelle colonne contenant le résultat. Cette colonne sera nommée du nom de la fonction utilisée.

📌 Cas pratique

Considérons la table videos, comptabilisant le nombre de vues pour chaque vidéo d’un Youtubeur :

idtitrevues
1Apprendre HTML/CSS en 1h chrono190 652
2Daily.dev, cette extension navigateur que vous devez avoir23 000
3Top 5 des raisons de devenir développeur, la dernière va vous étonner675 032

La requête suivante permet de connaître le nombre de vues total, moyen, maximal ainsi que le nombre de vidéos de la chaîne YouTube.

copié !
SELECT
SUM(vues) AS total,
AVG(vues) AS moyenne,
MAX(vues) AS record,
COUNT(vues) AS videos
FROM videos;
totalmoyennerecordvideos
888 684296 228675 0323

Groupement

Bien souvent, il est utile de grouper des données par colonne et d’utiliser une fonction statistique d’agrégation sur un groupe de résultats. On utilisera pour cela la commande GROUP BY.

copié !
SELECT colonne_1, FONCTION(colonne_2)
FROM nom_table
GROUP BY colonne_1;
📌 Cas pratique

Considérons la table transactions, regroupant les achats des utilisateurs d’une plateforme de cryptomonnaie :

idpseudodevisequantite
1YindiBTC0.55
2AthiosSOL20
3HackayBTC2.25
4HackayETH17
5YindiSOL5
6AthiosSOL15
7YindiBTC0.10

La requête suivante permet de connaître la quantité totale achetée pour chacune des cryptos.

copié !
SELECT devise, SUM(quantite) AS total
FROM transactions
GROUP BY devise;
devisetotal
BTC2.9
ETH17
SOL40

La requête suivante permet de connaître la quantité achetée par crypto, par utilisateur.

copié !
SELECT pseudo, devise, SUM(quantite) as total
FROM transactions
GROUP BY pseudo, devise;
pseudodevisetotal
AthiosSOL35
HackayBTC2.25
HackayETH17
YindiBTC0.65
YindiSOL5

Filtrage

Filtrer sur un tuple

Dans une requête SQL, la commande WHERE permet d’extraire des lignes d’une base de données respectant une condition. Cette clause vient compléter un SELECT de la manière suivante :

copié !
SELECT * FROM nom_table WHERE {condition};

Filtrer sur un groupe de tuples

Si un SELECT est combiné à un GROUP BY, il sera également possible de spécifier une condition de filtre non pas sur une ligne individuelle (WHERE) mais sur une agrégation de lignes avec la commande HAVING.

Pour rappel, cette agrégation est possible grâce à des fonctions statistiques comme COUNT(), SUM(), AVG(), MIN() ou encore MAX().

copié !
SELECT * FROM nom_table GROUP BY colonne HAVING {condition};

Ecrire une condition

Opérateurs de comparaison

Pour écrire une condition, on fait appel à des opérateurs de comparaison.

copié !
SELECT * FROM nom_table WHERE colonne {operateur_de_comparaison} valeur;
Opérateurs de comparaisons génériques

Ces opérateurs de comparaisons génériques sont identiques aux opérateurs élémentaires utilisés en algorithmie.

OpérateurDescriptionExemple
=Égalcolonne = ‘truc’
<> ou !=Différentcolonne != ‘truc’
>Supérieurcolonne > 20
<Inférieurcolonne < 20
>=Supérieur ou égalcolonne >= 20
<=Inférieur ou égalcolonne <= 20
Opérateurs de comparaison spécifiques

En plus des opérateurs de comparaison universels, SQL propose des opérateurs spécifiques au langage, permettant d’écrire des requêtes plus simplement.

Ces opérateurs sont les suivants :

OpérateurDescriptionExemple
INListe de plusieurs valeurs possiblescolonne IN (‘machin’, ‘bidule’, ‘truc’)
BETWEENValeur comprise dans un intervalle donné (très utile pour les nombres et dates)colonne BETWEEN 1 AND 10
LIKERecherche en spécifiant le début, milieu ou fin d’un mot.colonne LIKE ‘%.com’
IS NULLValeur est nullecolonne IS NULL
IS NOT NULLValeur n’est pas nullecolonne IS NOT NULL

SELECT * FROM nom_table WHERE colonne IN ('machin', 'bidule', 'truc') permet d’éviter d’écrire :

copié !
SELECT * FROM nom_table WHERE
colonne = 'machin' OR
colonne = 'bidule' OR
colonne = 'truc';

On qualifie cela de « sucre syntaxique ». Le sucre syntaxique constitue une écriture propre à un langage (ici SQL) qui permet d’écrire et de lire une expression de manière plus agréable, plus simple et expressive.

Opérateurs logiques

AND et OR

Comme il est souvent utile de vérifier la véracité de plusieurs conditions, il existe les opérateurs AND et OR qui permettent de cumuler des conditions.

copié !
SELECT * FROM nom_table WHERE condition_1 AND_ou_OR condition_2;
OpérateurDescriptionExemple
ANDLes deux conditions doivent être vraies.condition_1 AND condition_2
ORAu moins une des conditions doit être vraie.condition_1 OR condition_2
NOT

Il existe également l’opérateur NOT qui va quant à lui nous servir à vérifier qu’une condition écrite avec les opérateurs (LIKE, BETWEEN ou encore LIKE) n’est pas vraie.

OpérateurDescriptionExemple
NOTVérifie qu’une condition n’est pas vraie.colonne NOT IN (‘machin’, ‘bidule’, ‘truc’)
📌 Cas pratique

Considérons la table utilisateurs stockant des utilisateurs, leur âge et le fait qu’ils soient vaccinés contre la grippe ou non :

idprenomagevaccine
1Pierre370
2Paul551
3Jacques141

La requête suivante permet de connaître le nombre de majeurs vaccinés contre la grippe.

copié !
SELECT COUNT(id) FROM utilisateurs
WHERE age >= 18 AND vaccine = 1;
idprenomagevaccine
2Paul551
📌 Cas pratique

Considérons la table notes stockant les notes de collégiens obtenues au cours d’une année scolaire :

idprenomnomnote
1PierreMachin12
2PaulBidule20
3JacquesTruc10.5
4JacquesTruc8
5PierreMachin16
6PaulBidule13

La requête suivante permet d’afficher la liste des étudiants qui ont plus de 10/20 de moyenne générale.

copié !
SELECT prenom, nom
FROM notes
GROUP BY prenom, nom
HAVING AVG(note) >= 10;
prenomnom
PaulBidule
PierreMachin

Tri

Trier les données renvoyées par une requête est possible avec la commande ORDER BY.

Cette commande doit être suivie d’un mot-clé caractérisant le sens de tri souhaité :

  • ASC (ascendant) : croissant, alphabétique ou chronologique.
  • DESC (descendant) : décroissant, anti-alphabétique ou anti-chronologique.
copié !
SELECT * FROM nom_table ORDER BY colonne_1 ASC, colonne_2 DESC;
📌 Cas pratique

Considérons la table utilisateurs stockant des utilisateurs, leur âge et le fait qu’ils soient vaccinés contre la grippe ou non :

idprenomagevaccine
1Pierre370
2Paul551
3Jacques141

La requête suivante permet d’afficher la liste des utilisateurs vaccinés par âge décroissant.

copié !
SELECT * FROM utilisateurs
WHERE vaccine = 1
ORDER BY age DESC;
idprenomagevaccine
2Paul551
3Jacques141

La requête suivante permet d’afficher les prénoms (sans doublons) des utilisateurs par ordre alphabétique.

copié !
SELECT DISTINCT prenom FROM utilisateurs
ORDER BY prenom;
prenom
Jacques
Paul
Pierre

Pagination

Limite

Parfois, il peut être intéressant de limiter le nombre de résultats que l’on souhaite récupérer (affichage des X derniers articles sur la page d’accueil d’un blog, pagination affichant Y produits par page, etc.).

Pour cela nous utiliserons la commande LIMIT en fin de requête.

copié !
SELECT * FROM nom_table ORDER BY colonne DESC LIMIT nombre_limite;

Décalage

Parfois, il est utile de décaler les lignes à obtenir. C’est-à-dire qu’au lieu de récupérer les X dernières ressources, on souhaiterait récupérer X ressources en sautant un certain nombre de résultats. On parle d’offset.

On précisera alors cet offset avant la limite, séparé d’une virgule ,.

copié !
SELECT * FROM nom_table ORDER BY colone DESC LIMIT nombre_decalage, nombre_limite;

La meilleure manière de comprendre cette notion est de penser à un système de pagination :

  • Page 1 : Je souhaite récupérer les 10 derniers ***.
  • Page 2 : Je souhaite récupérer les 10 *** suivants (je saute les 10 premiers).
  • Page 3 : Je souhaite récupérer les 10 *** suivants (je saute les 20 premiers).
  • Etc.
📌 Cas pratique

Considérons la table produits stockant des produits sur un site ecommerce :

idnomprix
1PC portable DELL XPS 151800
2Souris MX Master 3105
3Webcam Logitech C920 HD PRO90
4Smartphone Xiaomi MI 9T PRO450
5Ecran Asus ProArt PA248QV260
6Hub USB Type-C Lemorele35
7Tapis de souris Steelseries Qck50

La requête suivante permet d’afficher les 3 produits les moins chers :

copié !
SELECT * FROM produits
ORDER BY prix
LIMIT 3;
idnomprix
6Hub USB Type-C Lemorele35
7Tapis de souris Steelseries Qck50
3Webcam Logitech C920 HD PRO90

La requête suivante permet d’afficher les produits du 7ᵉ au 9ᵉ moins chers :

copié !
SELECT * FROM produits
ORDER BY prix
LIMIT 6, 3;
idnomprix
1PC portable DELL XPS 151800

Jointures

Les jointures en SQL permettent d’obtenir des résultats qui combinent des données de plusieurs tables liées entre elles. Basées sur la théorie mathématique des ensembles, elles sont l’essence même du potentiel offert par les bases de données dites relationnelles.

Pour bien comprendre l’intérêt des jointures et par extension des relations, écrivons une aberration. Voici une table articles qui stocke les articles d’un blog.

idtitrecontenudate_publicationauteur_prenomauteur_nomauteur_bio
1Article n°1Blablabla2022-01-17JohnDoeJ’aime la vie.
2Article n°2Blablabla blablabla blablabla2019-12-03JamesBakelsExpert en BDD relationnelles.
3Article n°3Blablabla blablabla2021-05-14JohnDoeJ’aime la vie.
3Article n°4Blablabla blablabla2017-09-10JohnDoeJ’aime la vie.
3Article n°5Blablabla blablabla blablabla2020-06-29JamesBakelsExpert en BDD relationnelles.

Plusieurs problèmes évidents se dégagent de cette structure :

  • ❌ Une base de données trop lourde par duplication d’informations.
  • ❌ Une base de données brouillon, avec des types d’informations mélangés.
  • ❌ Une base de données non évolutive.
    • Admettons qu’un auteur souhaite modifier sa biographie ; il faudra modifier autant de lignes qu’il a écrit d’articles.
    • Si on souhaite ajouter une caractéristique à un auteur, alors il faudra la mettre à jour autant de fois qu’il a écrit d’articles.

Pour pallier à ces problématiques, la solution est de séparer ces informations en deux tables dont le rôle de chacune va être de stocker un type d’information spécifique.

Table articles

idtitrecontenudate_publicationauteur_id
1Article n°1Blablabla2022-01-171
2Article n°2Blablabla blablabla blablabla2019-12-032
3Article n°3Blablabla blablabla2021-05-141
4Article n°4Blablabla blablabla2017-09-101
5Article n°5Blablabla blablabla blablabla2020-06-292

Table auteurs

idprenomnombio
1JohnDoeJ’aime la vie.
2JamesBakelsExpert en BDD relationnelles.

Maintenant que vous êtes convaincus, parlons jointures !

En SQL, il existe plusieurs types de jointures, mais la plupart du temps nous utilisons la même, à savoir le INNER JOIN. Il s’agit littéralement d’une « jointure interne », permettant de retourner les enregistrements liés par une valeur commune au sein de deux tables, définie via le mot-clé ON.

copié !
SELECT * FROM table_1
INNER JOIN table_2 ON table_1.fk_id = table_2.id;

Cette syntaxe stipule qu’il faut sélectionner les enregistrements des tables table_1 et table_2 lorsque la clé étrangère de la table_1 (table_1.fk_id) est égale à la clé primaire de la table_2 (table_2.id).

📌 Cas pratique

Reprenons nos tables articles et auteurs :

La requête suivante permet d’afficher les articles publiés par John Doe :

copié !
SELECT articles.titre FROM articles 
INNER JOIN auteurs ON articles.auteur_id = auteurs.id
WHERE auteurs.prenom = 'John' AND auteurs.nom = 'Doe';
titre
Article n°2
Article n°5

Requêtes imbriquées

Dans le langage SQL une sous-requête (aussi appelé « requête imbriquée ») consiste à intégrer une requête SQL à l’intérieur d’une autre.

Les requêtes imbriquées sont notées entre parenthèses et peuvent être intégrées à diverses parties de la requête parente. Habituellement, elles sont exploitées dans une clause WHERE ou HAVING, bien que leur utilisation ne soit pas limitée à cela.

Une requête imbriquée peut alors retourner :

  • Une valeur
  • Un enregistrement
  • Plusieurs enregistrements
📌 Cas pratique

Considérons la table produits, répertoriant les produits d’un site ecommerce :

Table produits

idnomprix
1Produit n°110
2Produit n°230
3Produit n°38
4Produit n°412
copié !
SELECT * FROM produits WHERE prix > (SELECT AVG(prix) FROM produits);

Cette requête permet de récupérer les produits dont le prix est supérieur au prix moyen (ici 15).

idnomprix
2Produit n°230

En permettant d’utiliser les résultats d’une requête à l’intérieur d’une autre, les requêtes imbriquées permettent des opérations complexes et spécifiques (filtrages, comparaisons, agrégations complexes…).