Requêtes imbriquées en SQL

Le langage SQL vous permet d'imbriquer une requête dans une autre requête. Cela permet d'écrire une très grande requête qui fera quelque chose de grand et de complexe, bien que la lisibilité du code soit considérablement réduite.

Selon le nombre de valeurs renvoyées par les sous-requêtes, la zone où elles peuvent être appliquées change. Il y a trois options au total :

  • La sous-requête renvoie une seule valeur (une colonne et une ligne).
  • La sous-requête renvoie une liste de valeurs (un tableau avec une colonne).
  • La sous-requête renvoie une table (plusieurs colonnes, n'importe quel nombre de lignes).

Prenons un exemple pour chaque cas.

Sous-requête avec résultat scalaire

Trouvons une liste de tous nos employés de la table des employés dont le salaire est supérieur à la moyenne de l'entreprise. Comment pouvons-nous le faire?

Nous pouvons facilement filtrer les employés en comparant leur salaire à la moyenne si nous le connaissons à l'avance. Parallèlement, nous avons déjà écrit une requête qui nous permet de calculer le salaire moyen des employés de l'entreprise. Rappelons-le :

SELECT AVG(salary) FROM employee 

Puis MySQL nous a renvoyé la valeur : 76833.3333 .

Comment maintenant trouver une liste de tous les employés dont le salaire est supérieur à la moyenne ? C'est aussi très simple :

 SELECT * FROM employee 
   WHERE salary > 76833.3333 

Le résultat de cette requête sera :

identifiant nom profession salaire
1 Ivanov Ivan Programmeur 100000
2 Petrov Petr Programmeur 80000
4 Rabinovitch Moisha Directeur 200000

Et maintenant, nous combinons simplement les deux requêtes en substituant la première requête au lieu de la valeur 76833 :

   SELECT * FROM employee 
   WHERE salary > (SELECT AVG(salary) FROM employee) 

Le résultat de cette requête sera le même :

identifiant nom profession salaire
1 Ivanov Ivan Programmeur 100000
2 Petrov Petr Programmeur 80000
4 Rabinovitch Moisha Directeur 200000

Sous-requête avec liste de valeurs

Vous souvenez-vous d'une fois où nous avions une tâche - trouver tous les enregistrements d'une table pour lesquels il n'y a pas d'enregistrements correspondants d'une autre ?

Il y avait aussi cette photo :

Si je ne me trompe pas, la tâche est la suivante : afficher une liste de tous les employés de la table des employés pour lesquels il n'y a pas de tâches dans la table des tâches .

Trouvons également une solution en deux étapes.

Commençons par écrire une requête qui renverra l'identifiant de tous les employés qui ont des tâches dans la table des tâches. Rappelez-vous juste deux choses :

  • supprimer les doublons - utilisez le mot-clé DISTINCT.
  • supprimer les valeurs NULL ​​du résultat.
SELECT DISTINCT employee_id FROM task 
   WHERE employee_id IS NOT NULL

Et ici, nous avons obtenu un beau résultat d'une telle demande:

id_employé
1
2
5
4
6

Écrivons-le temporairement pour plus de commodité sous la forme d'une séquence : 1,2,5,4,6. Écrivons maintenant une deuxième requête - dans la table employee, qui renverra une liste d'employés dont l'id n'est pas contenu dans la première liste :

SELECT * FROM employee  
WHERE id NOT IN (1,2,5,4,6)

Et le résultat de cette requête :

identifiant nom profession salaire âge join_date
3 Ivanov Sergueï Testeur 40000 trente 2014-01-01

Et maintenant, comme dans l'exemple précédent, vous pouvez combiner les deux requêtes en remplaçant simplement le corps de la première requête au lieu de la liste d'identifiants.

 SELECT * FROM employee 
   WHERE id NOT IN ( 
      	SELECT DISTINCT employee_id FROM task 
      	WHERE employee_id IS NOT NULL 
   )