Exercices SQL corrigés : les fonctions texte et dates

Exercices SQL corrigés : les fonctions texte et dates

Mis à jour le

Textes et dates : UPPER, LOWER, LENGTH, SUBSTR, ||, LIKE, strftime, julianday, date. Ces 15 exercices vont du niveau 2 au niveau 8 ; ils utilisent la syntaxe de SQLite, le moteur SQL de SpeedQL.

Conseil : Dans LIKE, % remplace n’importe quelle suite de caractères et _ un seul caractère.

Relire la fiche « Texte et dates » de l’aide-mémoire

Exercice 1 · niveau 2

Affiche le nom des clients dont le nom commence par la lettre C.

Table customers (4 lignes)
idnamecity
1AliceParis
2BrunoLyon
3ChloeParis
4DylanNantes
Voir l’indice

Notions à utiliser : WHERE (filtres), Texte et dates.

Structure de la requête :

SELECT 
FROM 
WHERE  LIKE 
Voir la correction
SELECT name
FROM customers
WHERE name LIKE 'C%';

Résultat attendu (1 ligne) :

name
Chloe

Exercice 2 · niveau 4

Affiche l'id des factures émises en mars 2025.

Table invoices (6 lignes)
idclientissueddueamountpaid_on
1Acme2025-01-152025-02-1412002025-02-10
2Acme2025-03-012025-03-16800NULL
3Bolt2025-01-202025-03-064502025-03-01
4Bolt2025-02-252025-03-279502025-04-02
5Cyan2025-03-052025-05-04300NULL
6Cyan2024-12-102024-12-306002025-01-05
Voir l’indice

Notions à utiliser : WHERE (filtres), Texte et dates.

Structure de la requête :

SELECT 
FROM 
WHERE STRFTIME(, ) = 
Voir la correction
SELECT id
FROM invoices
WHERE strftime('%Y-%m', issued) = '2025-03';

Résultat attendu (2 lignes) :

id
2
5

Exercice 3 · niveau 4

Affiche l'id de chaque facture et le nombre de jours entre sa date d'émission et son échéance.

Table invoices (6 lignes)
idclientissueddueamountpaid_on
1Acme2025-01-152025-02-1412002025-02-10
2Acme2025-03-012025-03-16800NULL
3Bolt2025-01-202025-03-064502025-03-01
4Bolt2025-02-252025-03-279502025-04-02
5Cyan2025-03-052025-05-04300NULL
6Cyan2024-12-102024-12-306002025-01-05
Voir l’indice

Notions à utiliser : Texte et dates.

Structure de la requête :

SELECT , CAST(JULIANDAY() - JULIANDAY() AS INTEGER)
FROM 
Voir la correction
SELECT id, CAST(julianday(due) - julianday(issued) AS INTEGER)
FROM invoices;

Résultat attendu (6 lignes) :

idCAST(julianday(due) - julianday(issued) AS INTEGER)
130
215
345
430
560
620

Exercice 4 · niveau 4

Affiche le nom de chaque contact en majuscules, puis la longueur de ce nom.

Table contacts (5 lignes)
idnameemailphonecity
1Alice Martinalice@mail.com0612345678Paris
2bob durandNULL0698765432Lyon
3CLAIRE ROUXclaire@work.orgNULLNULL
4David LefevreNULLNULLNantes
5Emma Petitemma@mail.com0611223344NULL
Voir l’indice

Notions à utiliser : Texte et dates.

Structure de la requête :

SELECT UPPER(), LENGTH()
FROM 
Voir la correction
SELECT UPPER(name), LENGTH(name)
FROM contacts;

Résultat attendu (5 lignes) :

UPPER(name)LENGTH(name)
ALICE MARTIN12
BOB DURAND10
CLAIRE ROUX11
DAVID LEFEVRE13
EMMA PETIT10

Exercice 5 · niveau 4

Affiche la date des matchs joués un dimanche (strftime('%w', …) vaut '0' le dimanche).

Table matches (10 lignes)
idplayed_onhome_idaway_idhome_goalsaway_goals
12025-08-021221
22025-08-033400
32025-08-095113
42025-08-102322
52025-08-164531
62025-08-171310
72025-08-232401
82025-08-243523
92025-08-304111
102025-08-315202
Voir l’indice

Notions à utiliser : WHERE (filtres), Texte et dates.

Structure de la requête :

SELECT 
FROM 
WHERE STRFTIME(, ) = 
Voir la correction
SELECT played_on
FROM matches
WHERE strftime('%w', played_on) = '0';

Résultat attendu (5 lignes) :

played_on
2025-08-03
2025-08-10
2025-08-17
2025-08-24
2025-08-31

Exercice 6 · niveau 4

Affiche le nom de chaque élève et son âge en années révolues au 2025-09-01 (un élève n'a pris un an que si son anniversaire est passé).

Table students (8 lignes)
idnameclassbirth_date
1AdeleA2009-03-14
2BrunoA2008-11-02
3CyrilB2009-07-21
4DinaB2009-01-30
5ElsaA2008-09-12
6FarahC2009-05-05
7GaelC2008-12-24
8HanaB2009-10-10
Voir l’indice

Notions à utiliser : Texte et dates.

Structure de la requête :

SELECT , CAST(STRFTIME(, ) AS INTEGER) - CAST(STRFTIME(, ) AS INTEGER) - (STRFTIME(, ) < STRFTIME(, ))
FROM 
Voir la correction
SELECT name, CAST(strftime('%Y', '2025-09-01') AS INTEGER) - CAST(strftime('%Y', birth_date) AS INTEGER) - (strftime('%m-%d', '2025-09-01') < strftime('%m-%d', birth_date))
FROM students;

Résultat attendu (8 lignes) :

nameCAST(strftime('%Y', '2025-09-01') AS INTEGER) - CAST(strftime('%Y', birth_date) AS INTEGER) - (strftime('%m-%d', '2025-09-01') < strftime('%m-%d', birth_date))
Adele16
Bruno16
Cyril16
Dina16
Elsa16
Farah16
Gael16
Hana15

Exercice 7 · niveau 4

Affiche l'id de chaque vol et son heure d'arrivée au format AAAA-MM-JJ HH:MM (heure de départ + durée).

Table flights (12 lignes)
idairlineorigindestdepartsduration_minpriceseats_soldcapacity
1SkyJetCDGMAD2025-06-01 08:1012589150180
2AirNovaCDGLIS2025-06-01 11:40155120160170
3BlueWingLYSFCO2025-06-02 07:309575110150
4SkyJetMADCDG2025-06-02 18:2012095170180
5AirNovaBERCDG2025-06-03 09:05110105140160
6BlueWingNCEBER2025-06-03 13:5013014090150
7SkyJetCDGFCO2025-06-04 06:4513599175180
8AirNovaLISMAD2025-06-04 16:15756560120
9BlueWingFCOLYS2025-06-05 20:3010082130150
10SkyJetCDGBER2025-06-05 10:00105110120180
11AirNovaMADLIS2025-06-06 12:25807095120
12BlueWingLYSMAD2025-06-06 15:4011579100150
Voir l’indice

Notions à utiliser : Texte et dates.

Structure de la requête :

SELECT , STRFTIME(, ,  ||  || )
FROM 
Voir la correction
SELECT id, strftime('%Y-%m-%d %H:%M', departs, '+' || duration_min || ' minutes')
FROM flights;

Résultat attendu (12 lignes) :

idstrftime('%Y-%m-%d %H:%M', departs, '+' || duration_min || ' minutes')
12025-06-01 10:15
22025-06-01 14:15
32025-06-02 09:05
42025-06-02 20:20
52025-06-03 10:55
62025-06-03 16:00
72025-06-04 09:00
82025-06-04 17:30
92025-06-05 22:10
102025-06-05 11:45
112025-06-06 13:45
122025-06-06 17:35

Exercice 8 · niveau 4

Affiche l'id et une colonne route au format ORIGINE-DESTINATION (par exemple CDG-MAD) des vols des compagnies dont le nom commence par 'Air' ou par 'Blue' (colonnes : id, route).

Table flights (12 lignes)
idairlineorigindestdepartsduration_minpriceseats_soldcapacity
1SkyJetCDGMAD2025-06-01 08:1012589150180
2AirNovaCDGLIS2025-06-01 11:40155120160170
3BlueWingLYSFCO2025-06-02 07:309575110150
4SkyJetMADCDG2025-06-02 18:2012095170180
5AirNovaBERCDG2025-06-03 09:05110105140160
6BlueWingNCEBER2025-06-03 13:5013014090150
7SkyJetCDGFCO2025-06-04 06:4513599175180
8AirNovaLISMAD2025-06-04 16:15756560120
9BlueWingFCOLYS2025-06-05 20:3010082130150
10SkyJetCDGBER2025-06-05 10:00105110120180
11AirNovaMADLIS2025-06-06 12:25807095120
12BlueWingLYSMAD2025-06-06 15:4011579100150
Voir l’indice

Notions à utiliser : WHERE (filtres), Texte et dates.

Structure de la requête :

SELECT ,  ||  ||  AS 
FROM 
WHERE  LIKE  OR  LIKE 
Voir la correction
SELECT id, origin || '-' || dest AS route
FROM flights
WHERE airline LIKE 'Air%' OR airline LIKE 'Blue%';

Résultat attendu (8 lignes) :

idroute
2CDG-LIS
3LYS-FCO
5BER-CDG
6NCE-BER
8LIS-MAD
9FCO-LYS
11MAD-LIS
12LYS-MAD

Exercice 9 · niveau 4

Affiche le titre de chaque chanson et sa durée au format minutes:secondes, avec toujours 2 chiffres pour les secondes (par exemple 3:34 ou 4:01), dans une colonne mmss (colonnes : title, mmss).

Table songs (10 lignes)
idtitleartist_idgenreduration_sreleased
1Glass Heart1Pop2142019-04-12
2Low Tide1Pop1982021-06-01
3Rust2Rock2562008-09-30
4Wires2Rock3012015-02-14
5Sunday Market3Afrobeat2332020-11-20
6Palm Wine3Afrobeat2452022-03-03
7Alma4Latin1892013-07-07
8Brisa4Pop2052018-05-25
9Night Drive5Electro2762021-10-10
10Pulse5Electro2302023-01-15
Voir l’indice

Notions à utiliser : Texte et dates.

Structure de la requête :

SELECT , ( / ) ||  || PRINTF(,  % ) AS 
FROM 
Voir la correction
SELECT title, (duration_s / 60) || ':' || printf('%02d', duration_s % 60) AS mmss
FROM songs;

Résultat attendu (10 lignes) :

titlemmss
Glass Heart3:34
Low Tide3:18
Rust4:16
Wires5:01
Sunday Market3:53
Palm Wine4:05
Alma3:09
Brisa3:25
Night Drive4:36
Pulse3:50

Exercice 10 · niveau 4

Affiche la ville, le jour et, dans une colonne weekday, le jour de la semaine en anglais abrégé sur 3 lettres (Sun, Mon, Tue, Wed, Thu, Fri, Sat), pour les relevés où la température maximale dépasse 25 degrés (colonnes : city, day, weekday).

Table readings (15 lignes)
idcitydaytemp_maxtemp_minrain_mm
1Paris2025-07-0124150
2Paris2025-07-0227170
3Paris2025-07-0322164.5
4Paris2025-07-04191412
5Paris2025-07-0523130
6Lyon2025-07-0126160
7Lyon2025-07-0229180
8Lyon2025-07-0331190
9Lyon2025-07-0424178.5
10Lyon2025-07-0522153
11Marseille2025-07-0130210
12Marseille2025-07-0232220
13Marseille2025-07-0333230
14Marseille2025-07-0429210
15Marseille2025-07-0528200
Voir l’indice

Notions à utiliser : WHERE (filtres), Texte et dates.

Structure de la requête :

SELECT , , SUBSTR(,  +  * CAST(STRFTIME(, ) AS INTEGER), ) AS 
FROM 
WHERE  > 
Voir la correction
SELECT city, day, substr('SunMonTueWedThuFriSat', 1 + 3 * CAST(strftime('%w', day) AS INTEGER), 3) AS weekday
FROM readings
WHERE temp_max > 25;

Résultat attendu (9 lignes) :

citydayweekday
Paris2025-07-02Wed
Lyon2025-07-01Tue
Lyon2025-07-02Wed
Lyon2025-07-03Thu
Marseille2025-07-01Tue
Marseille2025-07-02Wed
Marseille2025-07-03Thu
Marseille2025-07-04Fri
Marseille2025-07-05Sat

Exercice 11 · niveau 4

Affiche le numéro de chaque réservation et son nombre de nuits (différence entre check_out et check_in, en jours entiers).

Table bookings (11 lignes)
idroom_idguest_idcheck_incheck_out
1212025-07-012025-07-04
2522025-07-022025-07-05
3832025-07-032025-07-06
4342025-07-052025-07-12
5652025-07-062025-07-08
6122025-07-082025-07-10
7932025-07-102025-07-11
8752025-07-112025-07-15
9412025-07-142025-07-16
10642025-07-152025-07-19
11652025-07-162025-07-18
Voir l’indice

Notions à utiliser : Texte et dates.

Structure de la requête :

SELECT , CAST(JULIANDAY() - JULIANDAY() AS INTEGER)
FROM 
Voir la correction
SELECT id, CAST(julianday(check_out) - julianday(check_in) AS INTEGER)
FROM bookings;

Résultat attendu (11 lignes) :

idCAST(julianday(check_out) - julianday(check_in) AS INTEGER)
13
23
33
47
52
62
71
84
92
104
112

Exercice 12 · niveau 4

Pour chaque mois (format AAAA-MM, avec strftime), affiche le mois, le nombre d'opérations et la somme des montants.

Table transactions (14 lignes)
idaccount_idmade_onamountlabel
112025-01-022500salary
212025-01-05-60groceries
312025-01-12-800rent
422025-01-15500transfer
532025-01-031900salary
632025-01-20-120groceries
732025-02-01-950rent
842025-01-252100salary
942025-02-03-45restaurant
1012025-02-022600salary
1112025-02-06-75groceries
1252025-02-1030interest
1322025-02-15500transfer
1442025-02-18-600rent
Voir l’indice

Notions à utiliser : COUNT, SUM, AVG, MIN, MAX, GROUP BY, Texte et dates.

Structure de la requête :

SELECT STRFTIME(, ), COUNT(*), SUM()
FROM 
GROUP BY STRFTIME(, )
Voir la correction
SELECT strftime('%Y-%m', made_on), COUNT(*), SUM(amount)
FROM transactions
GROUP BY strftime('%Y-%m', made_on);

Résultat attendu (2 lignes) :

strftime('%Y-%m', made_on)COUNT(*)SUM(amount)
2025-0176020
2025-0271460

Exercice 13 · niveau 5

Affiche les correspondances possibles (colonnes : id vol 1, id vol 2) : le vol 2 part de l'aéroport d'arrivée du vol 1, entre 0 et 48 heures après le départ du vol 1.

Table flights (12 lignes)
idairlineorigindestdepartsduration_minpriceseats_soldcapacity
1SkyJetCDGMAD2025-06-01 08:1012589150180
2AirNovaCDGLIS2025-06-01 11:40155120160170
3BlueWingLYSFCO2025-06-02 07:309575110150
4SkyJetMADCDG2025-06-02 18:2012095170180
5AirNovaBERCDG2025-06-03 09:05110105140160
6BlueWingNCEBER2025-06-03 13:5013014090150
7SkyJetCDGFCO2025-06-04 06:4513599175180
8AirNovaLISMAD2025-06-04 16:15756560120
9BlueWingFCOLYS2025-06-05 20:3010082130150
10SkyJetCDGBER2025-06-05 10:00105110120180
11AirNovaMADLIS2025-06-06 12:25807095120
12BlueWingLYSMAD2025-06-06 15:4011579100150
Voir l’indice

Notions à utiliser : JOIN, Texte et dates.

Structure de la requête :

SELECT , 
FROM  
JOIN   ON  =  AND JULIANDAY() - JULIANDAY() BETWEEN  AND 
Voir la correction
SELECT f.id, g.id
FROM flights f
JOIN flights g ON g.origin = f.dest AND julianday(g.departs) - julianday(f.departs) BETWEEN 0 AND 2;

Résultat attendu (6 lignes) :

idid
14
47
57
79
811
912

Exercice 14 · niveau 8

Affiche le nom des clients qui ont séjourné dans au moins 2 villes différentes, avec le nombre de villes et leur nombre total de nuits.

Table guests (6 lignes)
idnamecountry
1Ana SilvaPortugal
2Ben FordUSA
3Chen LiChina
4Dana WeissGermany
5Emma RoyFrance
6Farid NasserMorocco
Table bookings (11 lignes)
idroom_idguest_idcheck_incheck_out
1212025-07-012025-07-04
2522025-07-022025-07-05
3832025-07-032025-07-06
4342025-07-052025-07-12
5652025-07-062025-07-08
6122025-07-082025-07-10
7932025-07-102025-07-11
8752025-07-112025-07-15
9412025-07-142025-07-16
10642025-07-152025-07-19
11652025-07-162025-07-18
Table rooms (10 lignes)
idhotel_idtypeprice
11single70
21double95
32double130
42suite210
53single110
63double150
74double65
85double260
95suite480
105single190
Table hotels (5 lignes)
idnamecitystars
1Seaside InnNice3
2Alpine LodgeAnnecy4
3City LoftParis4
4Old MillBordeaux2
5Grand PalaceParis5
Voir l’indice

Notions à utiliser : COUNT, SUM, AVG, MIN, MAX, GROUP BY, JOIN, HAVING, Texte et dates.

Structure de la requête :

SELECT , COUNT(DISTINCT ), SUM(CAST(JULIANDAY() - JULIANDAY() AS INTEGER))
FROM  
JOIN   ON  = 
JOIN   ON  = 
JOIN   ON  = 
GROUP BY 
HAVING COUNT(DISTINCT ) >= 
Voir la correction
SELECT g.name, COUNT(DISTINCT h.city), SUM(CAST(julianday(b.check_out) - julianday(b.check_in) AS INTEGER))
FROM guests g
JOIN bookings b ON b.guest_id = g.id
JOIN rooms r ON r.id = b.room_id
JOIN hotels h ON h.id = r.hotel_id
GROUP BY g.id
HAVING COUNT(DISTINCT h.city) >= 2;

Résultat attendu (4 lignes) :

nameCOUNT(DISTINCT h.city)SUM(CAST(julianday(b.check_out) - julianday(b.check_in) AS INTEGER))
Ana Silva25
Ben Ford25
Dana Weiss211
Emma Roy28

Exercice 15 · niveau 8

Affiche le nom, la date d'inscription, la date de première commande et le délai en jours des clients dont la première commande a eu lieu moins de 300 jours après leur inscription.

Table customers (6 lignes)
idnamecitysignup
1AlbaParis2024-01-10
2BorisLyon2024-02-15
3CarlaParis2024-03-01
4DenisNantes2024-05-20
5EvaLyon2024-06-30
6FabioLille2024-08-08
Table orders (8 lignes)
idcustomer_idorder_datestatus
112025-01-05shipped
222025-01-12shipped
312025-02-03paid
432025-02-10cancelled
542025-02-20shipped
652025-03-02shipped
722025-03-15paid
832025-03-28shipped
Voir l’indice

Notions à utiliser : COUNT, SUM, AVG, MIN, MAX, GROUP BY, JOIN, HAVING, Texte et dates.

Structure de la requête :

SELECT , , MIN(), CAST(JULIANDAY(MIN()) - JULIANDAY() AS INTEGER)
FROM  
JOIN   ON  = 
GROUP BY 
HAVING JULIANDAY(MIN()) - JULIANDAY() < 
Voir la correction
SELECT c.name, c.signup, MIN(o.order_date), CAST(julianday(MIN(o.order_date)) - julianday(c.signup) AS INTEGER)
FROM customers c
JOIN orders o ON o.customer_id = c.id
GROUP BY c.id
HAVING julianday(MIN(o.order_date)) - julianday(c.signup) < 300;

Résultat attendu (2 lignes) :

namesignupMIN(o.order_date)CAST(julianday(MIN(o.order_date)) - julianday(c.signup) AS INTEGER)
Denis2024-05-202025-02-20276
Eva2024-06-302025-03-02245

S’entraîner avec correction automatique

Dans SpeedQL, tu écris ta requête et elle est vérifiée tout de suite, sur ces tables puis sur un jeu de données caché.

S’entraîner sur les 24 questions « Texte et dates »