L’opérateur SQL UNION

Dans cette leçon, nous allons découvrir un nouvel opérateur SQL : l’opérateur UNION et allons apprendre à l’utiliser pour combiner les résultats de deux déclarations SELECT ou pour simuler le comportement d’un FULL OUTER JOIN.

 

Conditions d’utilisation de l’opérateur SQL UNION

Nous allons utiliser l’opérateur SQL UNION pour combiner les résultats de deux déclarations SELECT.

Afin que cet opérateur fonctionne correctement et que les résultats puissent bien être combinés, il va falloir respecter les règles suivantes :

  • Chacun des SELECT dans un UNION doit posséder le même nombre de colonnes ;
  • Les colonnes doivent posséder le même type de données une à une dans chaque SELECT (la première colonne du premier SELECT doit posséder des données de même type que la première colonne du deuxième SELECT et etc.).

Notez bien que les colonnes sélectionnées peuvent avoir un nom différent entre les différents SELECT du moment que le type de données est le même. En cas de nom différent, et si nous voulons harmoniser les noms, nous pouvons tout à fait utiliser un alias.

Par défaut, l’opérateur SQL UNION ne va pas sélectionner les doublons dans les valeurs (les valeurs qui sont trouvées plusieurs fois n’apparaitront qu’une seule fois).

Nous allons par exemple pouvoir sélectionner la liste des noms et prénoms dans nos tables « users » et « employes » créées précédemment :

<!DOCTYPE html>
<html>
    <head>
        <title>Cours PHP / MySQL</title>
        <meta charset='utf-8'>
    </head>
    <body>
        <h1>Bases de données MySQL</h1>  
        <?php
            $servname = "localhost"; $dbname = "cours"; $user = "root"; $pass = "root";
            
            try{
                $dbco = new PDO("mysql:host=$servname;dbname=$dbname", $user, $pass);
                $dbco->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                
                /*L'opérateur SQL UNION*/
                $sth = $dbco->prepare("
                  SELECT nom, prenom FROM employes
                  UNION 
                  SELECT nom, prenom FROM users
                ");
                
                $sth-> execute();
                
                $resultat = $sth->fetchAll(PDO::FETCH_ASSOC);
                
                echo '<pre>';
                print_r($resultat);
                echo '</pre>';
            }
                  
            catch(PDOException $e){
                echo "Erreur : " . $e->getMessage();
            }
        ?>
    </body>
</html>

 

Présentation de l'opérateur sql union et exemple d'utilisation

Comme vous pouvez le voir, les valeurs dupliquées n’apparaissent qu’une fois. Notez bien qu’ici on sélectionne les noms et prénom dans chaque table qui vont représenter une entité et c’est bien sur cette entité nom + prénom que va être évaluée la duplication.

C’est pour cela qu’on a deux fois le prénom « Pierre » qui s’affiche, tout simplement car nos « Pierre » n’ont pas le même nom.

Si nous n’avions sélectionnés que les prénoms, le prénom « Pierre » ne se serait affiché qu’une fois :

<!DOCTYPE html>
<html>
    <head>
        <title>Cours PHP / MySQL</title>
        <meta charset='utf-8'>
    </head>
    <body>
        <h1>Bases de données MySQL</h1>  
        <?php
            $servname = "localhost"; $dbname = "cours"; $user = "root"; $pass = "root";
            
            try{
                $dbco = new PDO("mysql:host=$servname;dbname=$dbname", $user, $pass);
                $dbco->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                
                /*L'opérateur SQL UNION*/
                $sth = $dbco->prepare("
                  SELECT prenom FROM employes
                  UNION 
                  SELECT prenom FROM users
                ");
                
                $sth-> execute();
                
                $resultat = $sth->fetchAll(PDO::FETCH_ASSOC);
                
                echo '<pre>';
                print_r($resultat);
                echo '</pre>';
            }
                  
            catch(PDOException $e){
                echo "Erreur : " . $e->getMessage();
            }
        ?>
    </body>
</html>

 

Exemple d'utilisation d'union en sql avec pdo php

Si vous souhaitez obtenir toutes les valeurs (incluant les valeurs en double et etc.) alors il faudra utiliser UNION ALL.

<!DOCTYPE html>
<html>
    <head>
        <title>Cours PHP / MySQL</title>
        <meta charset='utf-8'>
    </head>
    <body>
        <h1>Bases de données MySQL</h1>  
        <?php
            $servname = "localhost"; $dbname = "cours"; $user = "root"; $pass = "root";
            
            try{
                $dbco = new PDO("mysql:host=$servname;dbname=$dbname", $user, $pass);
                $dbco->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                
                /*UNION ALL*/
                $sth = $dbco->prepare("
                  SELECT prenom, nom FROM employes
                  UNION ALL
                  SELECT prenom, nom FROM users
                ");
                        
                $sth-> execute();
                
                $resultat = $sth->fetchAll(PDO::FETCH_ASSOC);
                
                echo '<pre>';
                print_r($resultat);
                echo '</pre>';
            }
                  
            catch(PDOException $e){
                echo "Erreur : " . $e->getMessage();
            }
        ?>
    </body>
</html>

 

Exemple d'utilisation d'union all en sql avec pdo php

 

Utiliser l’opérateur UNION pour simuler un FULL OUTER JOIN en MySQL

Rappel : un FULL OUTER JOIN est un type de jointures externes qui va récupérer toutes les données pour les colonnes sélectionnées de chacune des deux tables.

Le mot clef FULL OUTER JOIN n’est pas supporté en tant que tel par MySQL. Nous allons cependant pouvoir simuler un FULL OUTER JOIN en utilisant un LEFT JOIN et un RIGHT JOIN avec une clause WHERE pour ne pas avoir les données présentes dans les deux tables en double dans notre résultat final et en combinant les résultats obtenus avec un UNION.

Pour rappel, un LEFT JOIN va nous permettre de récupérer toutes les données de notre table de gauche ainsi que les données de la table de droite qui satisfont à la condition dans la jointure.

Un RIGHT JOIN va lui nous permettre de récupérer toutes les données de notre table de droite ainsi que les données de la table de gauche qui satisfont à la condition dans la jointure.

Ainsi, en s’arrêtant là, nous allons avoir les données de la table de droite qui satisfont à la condition de notre LEFT JOIN et les données de la table de gauche qui satisfont à la condition de notre RIGHT JOIN en double (puisque notre RIGHT JOIN récupère déjà toutes les données de la table de droite et notre LEFT JOIN récupère déjà toutes les données de la table de gauche).

Ainsi, nous allons utiliser une clause WHERE soit dans notre LEFT JOIN soit dans notre RIGHT JOIN pour ne pas sélectionner plus de données que ce qu’on doit.

Attention, on ne parle pas ici de supprimer les résultats dupliqués, on veut seulement tenter de simuler le résultat d’un FULL OUTER JOIN et pour cela il ne faut pas aller sélectionner deux fois les mêmes résultats. Il est possible que l’on ait des valeurs dupliquées au final s’il y en a dans nos colonnes à la base.

Essayons de simuler le comportement d’un FULL OUTER JOIN qui sélectionnerait tous les prénoms et noms de notre table « users » et tous les contenus et les dates des commentaires de notre tables « comments » :

<!DOCTYPE html>
<html>
    <head>
        <title>Cours PHP / MySQL</title>
        <meta charset='utf-8'>
    </head>
    <body>
        <h1>Bases de données MySQL</h1>  
          <?php
              $servname = "localhost"; $dbname = "cours"; $user = "root"; $pass = "root";
              
              try{
                  $dbco = new PDO("mysql:host=$servname;dbname=$dbname", $user, $pass);
                  $dbco->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                  
                  //Simulation d'un FULL OUTER JOIN
                  $sth = $dbco->prepare("
                    SELECT u.prenom, u.nom, c.contenu, c.dateComment FROM users AS u
                    LEFT JOIN comments AS c ON u.id = c.userId
                    UNION ALL
                    SELECT u.prenom, u.nom, c.contenu, c.dateComment FROM users AS u
                    RIGHT JOIN comments AS c ON u.id = c.userId
                    WHERE u.id IS NULL
                  ");
                  
                  $sth-> execute();
                  
                  $resultat = $sth->fetchAll(PDO::FETCH_ASSOC);
                  
                  echo '<pre>';
                  print_r($resultat);
                  echo '</pre>';
              }
                    
              catch(PDOException $e){
                  echo "Erreur : " . $e->getMessage();
              }
          ?>
      </body>
</html>

 

Utilisation d'union en mysql pour simuler un full outer join sql avec pdo php

Ici, le premier SELECT sélectionne tous les prénoms et noms de notre table « users » ainsi que les contenus et dates de nos commentaires liés à un id utilisateur.

Le deuxième SELECT sélectionne lui uniquement les contenus et dates des commentaires qui n’ont pas d’utilisateur associé (WHERE u.id IS NULL).

En unissant ces deux SELECT avec un UNION ALL, cela nous permet donc d’obtenir tous les noms et prénoms de nos utilisateurs et tous les contenus et dates des commentaires.

Laisser un commentaire