• 40 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

Vous pouvez obtenir un certificat de réussite à l'issue de ce cours.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Mis à jour le 20/02/2019

Union de plusieurs requêtes

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Toujours dans l'optique de rassembler plusieurs requêtes en une seule, voici l'UNION.
Faire l'union de deux requêtes, cela veut simplement dire réunir les résultats de la première requête et les résultats de la seconde requête.
Voyons comment cela fonctionne !

Syntaxe

La syntaxe d'UNION  est simplissime : si vous avez deux requêtes SELECT  dont vous voulez additionner les résultats, il vous suffit d'ajouter UNION  entre ces deux requêtes.

SELECT ...
UNION
SELECT ...

Le nombre de requêtes qu'il est possible d'unir est illimité. Si vous avez cinquante requêtes de sélection, placez un UNION  entre les cinquante requêtes.

SELECT ...
UNION
SELECT ...
UNION
SELECT ...
....
UNION
SELECT ...

Par exemple, vous pouvez obtenir les chats et les tortues de la manière suivante :

SELECT Animal.* FROM Animal 
INNER JOIN Espece ON Animal.espece_id = Espece.id 
WHERE Espece.nom_courant = 'Chat'
UNION
SELECT Animal.* FROM Animal 
INNER JOIN Espece ON Animal.espece_id = Espece.id 
WHERE Espece.nom_courant = 'Tortue d''Hermann';

Les règles

Bien sûr, ce n'est pas si simple que cela, il faut respecter certaines contraintes.

Nombre de colonnes

Il est absolument indispensable que toutes les requêtes unies renvoient le même nombre de colonnes.

Dans la requête que l'on a écrite ci-dessus, aucun problème, puisque l'on sélectionne Animal.* dans les deux requêtes. Mais il ne serait donc pas possible de sélectionner un nombre de colonnes différent dans chaque requête intermédiaire.

Par exemple, la requête ci-dessous renverra une erreur :

-- Pas le même nombre de colonnes --
------------------------------------

SELECT Animal.id, Animal.nom, Espece.nom_courant                    
    -- 3 colonnes sélectionnées
FROM Animal
INNER JOIN Espece ON Animal.espece_id = Espece.id
WHERE Espece.nom_courant = 'Chat'
UNION
SELECT Animal.id, Animal.nom, Espece.nom_courant, Animal.espece_id 
    -- 4 colonnes sélectionnées
FROM Animal
INNER JOIN Espece ON Animal.espece_id = Espece.id
WHERE Espece.nom_courant = 'Tortue d''Hermann';
ERROR 1222 (21000): The used SELECT statements have a different number of columns
Type et ordre des colonnes

En ce qui concerne le type des colonnes, je pense vous avoir déjà signalé que MySQL est très (vraiment très) permissif. Par conséquent, si vous sélectionnez des colonnes de différents types, vous n'aurez pas d'erreur, mais vous aurez des résultats un peu… spéciaux. o_O

Prenons la requête suivante :

SELECT Animal.id, Animal.nom, Espece.nom_courant    
    -- 3e colonne : nom_courant VARCHAR
FROM Animal
INNER JOIN Espece ON Animal.espece_id = Espece.id
WHERE Espece.nom_courant = 'Chat' AND Animal.nom LIKE 'C%'
UNION
SELECT Animal.id, Animal.nom, Espece.id             
    -- 3e colonne : id SMALLINT
FROM Animal
INNER JOIN Espece ON Animal.espece_id = Espece.id
WHERE Espece.nom_courant = 'Tortue d''Hermann' AND Animal.nom LIKE 'C%';

Vous aurez bien un résultat :

id

nom

nom_courant

5

Choupi

Chat

33

Caribou

Chat

34

Capou

Chat

37

Callune

Chat

43

Cracotte

Chat

44

Cawette

Chat

50

Cheli

3

51

Chicaca

3

Mais avouez que ce n'est pas un résultat très cohérent. MySQL va simplement convertir tout en chaînes de caractères pour ne pas avoir de problème. Soyez donc très prudent !

Et enfin, pour l'ordre des colonnes, à nouveau, vous n'aurez pas d'erreur tant que vous aurez le même nombre de colonnes dans chaque requête, mais vous pourrez avoir des résultats bizarres. En effet, MySQL n'analyse pas les noms des colonnes pour trouver une quelconque correspondance d'une requête à l'autre ; tout se fait sur la base de la position de la colonne dans la requête.

SELECT Animal.id, Animal.nom, Espece.nom_courant FROM Animal
INNER JOIN Espece ON Animal.espece_id = Espece.id
WHERE Espece.nom_courant = 'Chat' AND Animal.nom LIKE 'C%'
UNION
SELECT Animal.nom, Animal.id, Espece.nom_courant FROM Animal   
    -- 1e et 2e colonnes inversées par rapport à la première requête
INNER JOIN Espece ON Animal.espece_id = Espece.id
WHERE Espece.nom_courant = 'Tortue d''Hermann' AND Animal.nom LIKE 'C%';

id

nom

nom_courant

5

Choupi

Chat

33

Caribou

Chat

34

Capou

Chat

37

Callune

Chat

43

Cracotte

Chat

44

Cawette

Chat

Cheli

50

Tortue d'Hermann

Chicaca

51

Tortue d'Hermann

UNION ALL

Exécutez la requête suivante :

SELECT * FROM Espece
UNION
SELECT * FROM Espece;

Non, non, je ne me suis pas trompé, je vous demande bien d'unir deux requêtes qui sont exactement les mêmes.

Résultat :

id

nom_courant

nom_latin

description

1

Chien

Canis canis

Bestiole à quatre pattes qui aime les caresses et tire souvent la langue

2

Chat

Felis silvestris

Bestiole à quatre pattes qui saute très haut et grimpe aux arbres

3

Tortue d'Hermann

Testudo hermanni

Bestiole avec une carapace très dure

4

Perroquet amazone

Alipiopsitta xanthops

Joli oiseau parleur vert et jaune

Chaque résultat n’apparaît qu'une seule fois, pour la simple et bonne raison que, lorsque vous faites UNION, les doublons sont effacés. En fait, UNION  est équivalent à UNION DISTINCT. Si vous voulez conserver les doublons, vous devez utiliser UNION ALL.

SELECT * FROM Espece
UNION ALL
SELECT * FROM Espece;

id

nom_courant

nom_latin

description

1

Chien

Canis canis

Bestiole à quatre pattes qui aime les caresses et tire souvent la langue

2

Chat

Felis silvestris

Bestiole à quatre pattes qui saute très haut et grimpe aux arbres

3

Tortue d'Hermann

Testudo hermanni

Bestiole avec une carapace très dure

4

Perroquet amazone

Alipiopsitta xanthops

Joli oiseau parleur vert et jaune

1

Chien

Canis canis

Bestiole à quatre pattes qui aime les caresses et tire souvent la langue

2

Chat

Felis silvestris

Bestiole à quatre pattes qui saute très haut et grimpe aux arbres

3

Tortue d'Hermann

Testudo hermanni

Bestiole avec une carapace très dure

4

Perroquet amazone

Alipiopsitta xanthops

Joli oiseau parleur vert et jaune

LIMIT et ORDER BY

LIMIT

Il est possible de restreindre les résultats avec LIMIT  au niveau de la requête entière, ou au niveau des différentes requêtes unies. L'important est que ce soit clair. Par exemple, vous unissez deux requêtes et vous voulez limiter les résultats de la première. La requête suivante est parfaite pour cela :

SELECT id, nom, 'Race' AS table_origine FROM Race LIMIT 3
UNION
SELECT id, nom_latin, 'Espèce' AS table_origine FROM Espece;

Vous avez bien trois noms de races, suivis de toutes les espèces.

id

nom

table_origine

1

Berger allemand

Race

2

Berger blanc suisse

Race

3

Boxer

Race

4

Alipiopsitta xanthops

Espèce

1

Canis canis

Espèce

2

Felis silvestris

Espèce

3

Testudo hermanni

Espèce

Par contre, si vous voulez limiter les résultats de la seconde requête, comment faire ? Essayons la requête suivante.

SELECT id, nom, 'Race' AS table_origine FROM Race
UNION
SELECT id, nom_latin, 'Espèce' AS table_origine FROM Espece LIMIT 2;

id

nom

table_origine

1

Berger allemand

Race

2

Berger blanc suisse

Race

Visiblement, ce n'est pas ce que nous voulions… En fait, LIMIT  a été appliqué à l'ensemble des résultats, après UNION. Par conséquent, si l'on veut que LIMIT  ne porte que sur la dernière requête, il faut le préciser. Pour cela, il suffit d'utiliser des parenthèses.

SELECT id, nom, 'Race' AS table_origine FROM Race
UNION
(SELECT id, nom_latin, 'Espèce' AS table_origine FROM Espece LIMIT 2);

id

nom

table_origine

1

Berger allemand

Race

2

Berger blanc suisse

Race

3

Boxer

Race

4

Bleu russe

Race

5

Maine coon

Race

6

Singapura

Race

7

Sphynx

Race

8

Nebelung

Race

4

Alipiopsitta xanthops

Espèce

1

Canis canis

Espèce

Et voilà le travail !

ORDER BY

Par contre, s'il est possible de trier le résultat final d'une requête avec UNION, on ne peut pas trier les résultats des requêtes intermédiaires. Par exemple, cette requête trie bien les résultats par ordre anti-alphabétique du nom :

SELECT id, nom, 'Race' AS table_origine FROM Race
UNION
SELECT id, nom_latin, 'Espèce' AS table_origine FROM Espece
ORDER BY nom DESC;

id

nom

table_origine

3

Testudo hermanni

Espèce

7

Sphynx

Race

6

Singapura

Race

8

Nebelung

Race

5

Maine coon

Race

2

Felis silvestris

Espèce

1

Canis canis

Espèce

3

Boxer

Race

4

Bleu russe

Race

2

Berger blanc suisse

Race

1

Berger allemand

Race

4

Alipiopsitta xanthops

Espèce

Vous pouvez bien sûr combiner LIMIT  et ORDER BY.

(SELECT id, nom, 'Race' AS table_origine FROM Race LIMIT 6)
UNION
(SELECT id, nom_latin, 'Espèce' AS table_origine FROM Espece LIMIT 3)
ORDER BY nom LIMIT 5;

id

nom

table_origine

4

Alipiopsitta xanthops

Espèce

1

Berger allemand

Race

2

Berger blanc suisse

Race

4

Bleu russe

Race

3

Boxer

Race

Exception pour les tris sur les requêtes intermédiaires

Je vous ai dit qu'il n'était pas possible de trier les résultats d'une requête intermédiaire. En réalité, c'est plus subtil que cela.
Dans une requête intermédiaire, il est possible d'utiliser un ORDER BY, mais uniquement combiné à un LIMIT. Cela permettra de restreindre les résultats voulus (les X premiers dans l'ordre défini par l'ORDER BY, par exemple).

Prenons la requête suivante :

(SELECT id, nom, 'Race' AS table_origine FROM Race LIMIT 6)
UNION
(SELECT id, nom_latin, 'Espèce' AS table_origine FROM Espece LIMIT 3);

Cela vous renvoie bien 6 races et 3 espèces, mais imaginons que vous ne vouliez pas n'importe quelles races, mais les 6 dernières par ordre alphabétique du nom. Dans ce cas-là, vous pouvez utiliser ORDER BY  en combinaison avec LIMIT  dans la requête intermédiaire :

(SELECT id, nom, 'Race' AS table_origine FROM Race ORDER BY nom DESC LIMIT 6)
UNION
(SELECT id, nom_latin, 'Espèce' AS table_origine FROM Espece LIMIT 3);

id

nom

table_origine

7

Sphynx

Race

6

Singapura

Race

8

Nebelung

Race

5

Maine coon

Race

3

Boxer

Race

4

Bleu russe

Race

4

Alipiopsitta xanthops

Espèce

1

Canis canis

Espèce

2

Felis silvestris

Espèce

En résumé
  • Pour grouper les résultats de deux requêtes SELECT, il suffit de placer UNION  entre les deux requêtes.

  • UNION  est équivalent à UNION DISTINCT. Si l'on ne veut pas éliminer les doublons, il faut utiliser UNION ALL.

  • Il est possible de limiter les résultats d'un UNION  (avec LIMIT), mais également de limiter les résultats de chaque requête composant l'UNION.

  • Par contre, ORDER BY  n'aura d'influence que s'il est utilisé sur le résultat final d'un UNION.

Exemple de certificat de réussite
Exemple de certificat de réussite