Comme son nom l'indique, ce chapitre traitera de la sélection et de l'affichage de données.
Au menu :
- syntaxe de la requête
SELECT
(que vous avez déjà croisée il y a quelque temps) ; - sélection de données répondant à certaines conditions ;
- tri des données ;
- élimination des données en double ;
- récupération de seulement une partie des données (uniquement les 10 premières lignes, par exemple).
Motivés ? Alors c'est parti !!
La requête qui permet de sélectionner et afficher des données s'appelle
SELECT
. Nous l'avons déjà un peu utilisée dans le chapitre d'installation, ainsi que pour afficher tout le contenu de la table Animal.SELECT
permet donc d'afficher des données directement. Des chaînes de caractères, des résultats de calculs, etc.
Exemple
SELECT 'Hello World !';
SELECT 3+2;
SELECT
permet également de sélectionner des données à partir d'une table. Pour cela, il faut ajouter une clause à la commande
SELECT
: la clause FROM
, qui définit de quelle structure (dans notre cas, une table) viennent les données.
SELECT colonne1, colonne2, ...
FROM nom_table;
Par exemple, si l'on veut sélectionner l'espèce, le nom et le sexe des animaux présents dans la tableAnimal, on utilisera :
SELECT espece, nom, sexe
FROM Animal;
Sélectionner toutes les colonnes
Si vous désirez sélectionner toutes les colonnes, vous pouvez utiliser le caractère * dans votre requête :
SELECT *
FROM Animal;
Il est cependant déconseillé d'utiliser
SELECT *
trop souvent. Donner explicitement le nom des colonnes dont vous avez besoin présente deux avantages :- d'une part, vous êtes certains de ce que vous récupérez ;
- d'autre part, vous récupérez uniquement ce dont vous avez vraiment besoin, ce qui permet d'économiser des ressources.
Le désavantage est bien sûr que vous avez plus à écrire, mais le jeu en vaut la chandelle.
Comme vous avez pu le constater, les requêtes
SELECT
faites jusqu'à présent sélectionnent toutes les lignes de la table. Or, bien souvent, on ne veut qu'une partie des données. Dans la suite de ce chapitre, nous allons voir ce que nous pouvons ajouter à cette requête SELECT
pour faire des sélections à l'aide de critères.
La clause
WHERE
("où" en anglais) permet de restreindre les résultats selon des critères de recherche. On peut par exemple vouloir ne sélectionner que les chiens :
SELECT *
FROM Animal
WHERE espece='chien';
Les opérateurs de comparaison
Les opérateurs de comparaison sont les symboles que l'ont utilise pour définir les critères de recherche (le = dans notre exemple précédent). Huit opérateurs simples peuvent être utilisés.
Opérateur
|
Signification
|
---|---|
=
|
égal
|
<
|
inférieur
|
<=
|
inférieur ou égal
|
>
|
supérieur
|
>=
|
supérieur ou égal
|
<> ou !=
|
différent
|
<=>
|
égal (valable pour
NULL aussi) |
Exemples :
SELECT *
FROM Animal
WHERE date_naissance < '2008-01-01'; -- Animaux nés avant 2008
SELECT *
FROM Animal
WHERE espece <> 'chat'; -- Tous les animaux sauf les chats
Combinaisons de critères
Tout ça c'est bien beau, mais comment faire si on veut les chats et les chiens par exemple ? Faut-il faire deux requêtes ?
Non bien sûr, il suffit de combiner les critères. Pour cela, il faut des opérateurs logiques, qui sont au nombre de quatre :
Non bien sûr, il suffit de combiner les critères. Pour cela, il faut des opérateurs logiques, qui sont au nombre de quatre :
Opérateur
|
Symbole
|
Signification
|
---|---|---|
AND |
&&
|
ET
|
OR |
||
|
OU
|
XOR |
OU exclusif
| |
NOT |
!
|
NON
|
Voici quelques exemples, sûrement plus efficaces qu'un long discours.
AND
Je veux sélectionner toutes les chattes. Je veux donc sélectionner les animaux qui sont à la fois des chats ET des femelles. J'utilise l'opérateur
AND
:
SELECT *
FROM Animal
WHERE espece='chat'
AND sexe='F';
-- OU
SELECT *
FROM Animal
WHERE espece='chat'
&& sexe='F';
OR
Sélection des tortues et des perroquets. Je désire donc obtenir les animaux qui sont des tortues OU des perroquets :
SELECT *
FROM Animal
WHERE espece='tortue'
OR espece='perroquet';
-- OU
SELECT *
FROM Animal
WHERE espece='tortue'
espece='perroquet';
||
NOT
Sélection de tous les animaux femelles sauf les chiennes.
SELECT *
FROM Animal
WHERE sexe='F'
AND NOT espece='chien';
-- OU
SELECT *
FROM Animal
WHERE sexe='F'
AND ! espece='chien';
XOR
Sélection des animaux qui sont soit des mâles, soit des perroquets (mais pas les deux) :
SELECT *
FROM Animal
WHERE sexe='M'
XOR espece='perroquet';
Et voilà pour les opérateurs logiques. Rien de bien compliqué, et pourtant, c'est souvent source d'erreur. Pourquoi ? Tout simplement parce que tant que vous n'utilisez qu'un seul opérateur logique, tout va très bien. Mais on a souvent besoin de combiner plus de deux critères, et c'est là que ça se corse.
Sélection complexe
Lorsque vous utilisez plusieurs critères, et que vous devez donc combiner plusieurs opérateurs logiques, il est extrêmement important de bien structurer la requête. En particulier, il faut placer des parenthèses au bon endroit. En effet, cela n'a pas de sens de mettre plusieurs opérateurs logiques différents sur un même niveau.
Petit exemple simple :
Critères : rouge
Petit exemple simple :
Critères : rouge
AND
vertOR
bleu
Qu'accepte-t-on ?
- Ce qui est rouge et vert, et ce qui est bleu ?
- Ou ce qui est rouge et, soit vert soit bleu ?
Dans le premier cas, [rouge, vert] et [bleu] seraient acceptés. Dans le deuxième, c'est [rouge, vert] et [rouge, bleu] qui seront acceptés, et non [bleu].
En fait, le premier cas correspond à (rouge
AND
vert) OR
bleu, et le deuxième cas à rougeAND
(vertOR
bleu).
Avec des parenthèses, pas moyen de se tromper sur ce qu'on désire sélectionner !
Exercice/Exemple
Alors, imaginons une requête bien tordue…
Je voudrais les animaux qui sont, soit nés après 2009, soit des chats mâles ou femelles, mais dans le cas des femelles, elles doivent être nées avant juin 2007.
Je vous conseille d'essayer d'écrire cette requête tout seuls. Si vous n'y arrivez pas, voici une petite aide : l'astuce, c'est de penser en niveaux. Je vais donc découper ma requête.
Je cherche :
- les animaux nés après 2009 ;
- les chats mâles et femelles (uniquement nées avant juin 2007 pour les femelles).
C'est mon premier niveau. L'opérateur logique sera
OR
puisqu'il faut que les animaux répondent à un seul des deux critères pour être sélectionnés.
On continue à découper. Le premier critère ne peut plus être subdivisé, contrairement au deuxième. Je cherche :
- les animaux nés après 2009 ;
- les chats :
- mâles ;
- et femelles nées avant juin 2007.
Et voilà, vous avez bien défini les différents niveaux, il n'y a plus qu'à écrire la requête avec les bons opérateurs logiques !
SELECT *
FROM Animal
WHERE date_naissance > '2009-12-31'
OR
( espece='chat'
AND
( sexe='M'
OR
( sexe='F' AND date_naissance < '2007-06-01' )
)
);
Le cas de NULL
Vous vous souvenez sans doute de la liste des opérateurs de comparaison que je vous ai présentée (sinon, retournez au début de la partie sur la clause
. Mais je vais me rattraper maintenant !
En fait, c'est très simple, le marqueur
WHERE
). Vous avez probablement été un peu étonnés de voir dans cette liste l'opérateur <=> : égal (valable aussi pour NULL
). D'autant plus que j'ai fait un peu semblant de rien et ne vous ai pas donné d'explication sur cette mystérieuse précision "aussi valable pour NULL
" En fait, c'est très simple, le marqueur
NULL
(qui représente donc "pas de valeur") est un peu particulier. En effet, vous ne pouvez pas tester directement colonne = NULL
. Essayons donc :
SELECT *
FROM Animal
WHERE nom = NULL; -- sélection des animaux sans nom
SELECT *
FROM Animal
WHERE commentaires <> NULL; -- sélection des animaux pour lesquels un commentaire existe
Comme vous pouvez vous en douter après ma petite introduction, ces deux requêtes ne renvoient pas les résultats que l'on pourrait espérer. En fait, elles ne renvoient aucun résultat. C'est donc ici qu'intervient notre opérateur de comparaison un peu spécial <=> qui permet de reconnaître
NULL
. Une autre possibilité est d'utiliser les mots-clés IS NULL
, et si l'on veut exclure les NULL
: IS NOT NULL
. Nous pouvons donc réécrire nos requêtes, correctement cette fois-ci :
SELECT *
FROM Animal
WHERE nom <=> NULL; -- sélection des animaux sans nom
-- OU
SELECT *
FROM Animal
WHERE nom IS NULL;
SELECT *
FROM Animal
WHERE commentaires IS NOT NULL; -- sélection des animaux pour lesquels un commentaire existe
Cette fois-ci, ça fonctionne parfaitement !
id
|
espece
|
sexe
|
date_naissance
|
nom
|
commentaires
|
---|---|---|---|---|---|
4
|
tortue
|
F
|
2009-08-03 05:12:00
|
NULL
|
NULL
|
9
|
tortue
|
NULL
|
2010-08-23 05:18:00
|
NULL
|
NULL
|
id
|
espece
|
sexe
|
date_naissance
|
nom
|
commentaires
|
---|---|---|---|---|---|
1
|
chien
|
M
|
2010-04-05 13:43:00
|
Rox
|
Mordille beaucoup
|
5
|
chat
|
NULL
|
2010-10-03 16:44:00
|
Choupi
|
Né sans oreille gauche
|
6
|
tortue
|
F
|
2009-06-13 08:17:00
|
Bobosse
|
Carapace bizarre
|
35
|
chat
|
M
|
2006-05-19 16:56:00
|
Raccou
|
Pas de queue depuis la naissance
|
52
|
tortue
|
F
|
2006-03-15 14:26:00
|
Redbul
|
Insomniaque
|
55
|
tortue
|
M
|
2008-03-15 18:45:00
|
Relou
|
Surpoids
|
Lorsque vous faites un
SELECT
, les données sont récupérées dans un ordre défini par MySQL, mais qui n'a aucun sens pour vous. Vous avez sans doute l'impression que MySQL renvoie tout simplement les lignes dans l'ordre dans lequel elles ont été insérées, mais ce n'est pas exactement le cas. En effet, si vous supprimez des lignes, puis en ajoutez de nouvelles, les nouvelles lignes viendront remplacer les anciennes dans l'ordre de MySQL. Or, bien souvent, vous voudrez trier à votre manière. Par date de naissance par exemple, ou bien par espèce, ou par sexe, etc.
Pour trier vos données, c'est très simple, il suffit d'ajouter
ORDER BY tri
à votre requête (après les critères de sélection de WHERE
s'il y en a) et de remplacer "tri" par la colonne sur laquelle vous voulez trier vos données bien sûr.
Par exemple, pour trier par date de naissance :
SELECT *
FROM Animal
WHERE espece='chien'
ORDER BY date_naissance;
Et hop ! Vos données sont triées, les plus vieux chiens sont récupérés en premier, les jeunes à la fin.
Tri ascendant ou descendant
Tout ça c'est bien beau, j'ai mes chiens triés du plus vieux au plus jeune. Et si je veux le contraire ?
Pour déterminer le sens du tri effectué, SQL possède deux mots-clés :
Si par contre vous utilisez le mot
Pour déterminer le sens du tri effectué, SQL possède deux mots-clés :
ASC
pour ascendant, et DESC
pour descendant. Par défaut, si vous ne précisez rien, c'est un tri ascendant qui est effectué : du plus petit nombre au plus grand, de la date la plus ancienne à la plus récente, et pour les chaînes de caractères et les textes, c'est l'ordre alphabétique normal qui est utilisé.Si par contre vous utilisez le mot
DESC
, l'ordre est inversé : plus grand nombre d'abord, date la plus récente d'abord, et ordre anti-alphabétique pour les caractères.
SELECT *
FROM Animal
WHERE espece='chien'
AND nom IS NOT NULL
ORDER BY nom DESC;
Trier sur plusieurs colonnes
Il est également possible de trier sur plusieurs colonnes. Par exemple, si vous voulez que les résultats soient triés par espèce et, dans chaque espèce, triés par date de naissance, il suffit de donner les deux colonnes correspondantes à
ORDER BY
:
SELECT *
FROM Animal
ORDER BY espece, date_naissance;
Vous pouvez trier sur autant de colonnes que vous voulez.