Requête SQL Union disjoint

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour à tous,

Voilà je souhaite faire une requête de type union disjoint, comment procéder ? Y a t-il une erreur dans ce code ?

1
2
3
4
SELECT nom FROM user1
UNION
SELECT nom FROM user2
WHERE user1.nom NOT IN (SELECT nom FROM user2)
+0 -0

C'est quoi le but ? Récupérer tous les noms qui sont dans user1 mais pas dans user2 ?

Parce que si c'est ça que tu veux, je pense qu'il serait mieux d'écrire quelque chose dans ce goût-là :

1
2
3
4
5
select nom from user1 u1
where not exists (
select nom  from user2 u2
where u1.nom=u2.nom
)

S'il y a des index sur les noms, c'est un parcours de la table user1 et des requêtes quasiment gratuites sur user2.

Pour une différence symétrique, il y a juste à rajouter une union et une requête similaire dans l'autre sens.

Ma plateforme avec 23 jeux de société classiques en 6 langues et 13000 joueurs: http://qcsalon.net/ | Apprenez à faire des sites web accessibles http://www.openweb.eu.org/

+0 -0

QuentinC, tu es sur que ta requête fonctionne ?

JE n'ai absolument pas testé, j'ai tapé le code directement dans la zone de réponse. Mais je suis sûr à 99% que ça fonctionne, moyennant peutêtre des erreurs de syntaxe basiques.

Par contre tu n'as pas répondu à la question la plus importante et pour moi le contexte n'est pas totalement clair: Quel est le but ? Dit autrement, qu'est-ce que tu cherches à obtenir ? Parce que si ça se trouve ma réponse est complètement à l'ouest, et en fait je crois qu'effectivement à te lire maintenant j'ai répondu à une question que tu ne te posais pas.

Si on admet que la table user1 contient {A, B, C, D, E} et user2 {C, D, E, F, G}, alors la requête que j'ai suggéré ce matin te retournera {A, B}, et la remarque qui suit te permettra d'obtenir {A, B, F, G}.

Sans même essayer, je pense que ta requête à toi te renverra {A, B, C, D, E, F, G}. Est-ce bien ce que tu souhaites ? Par contre je ne pense pas que ce soit la manière la plus efficace d'y arriver.

Si tu veux bel et bien {A, B, C, D, E, F; G}, je pense que ceci est plus rapide que ce que tu proposes :

1
2
3
4
select nom from user1
union
select nom from user2 u2
where not exists( select nom from user1 u1 where u1.nom=u2.nom)

A condition qu'il y ait des index sur les noms, à mon avis not in est beaucoup plus lent.

Ma plateforme avec 23 jeux de société classiques en 6 langues et 13000 joueurs: http://qcsalon.net/ | Apprenez à faire des sites web accessibles http://www.openweb.eu.org/

+1 -0

Si on admet que la table user1 contient {A, B, C, D, E} et user2 {C, D, E, F, G}, alors la requête que j'ai suggéré ce matin te retournera {A, B}

QuentinC

Sinon tu as :

1
2
3
select nom from user1
intersect
select nom from user2

… pour obtenir le même résultat.

, et la remarque qui suit te permettra d'obtenir {A, B, F, G}.

QuentinC

A vrai dire la requête que j'ai indiqué retourne {A, B, C, D, E, F, G}, c'est une requête inutile dans le sens où elle est équivalente à :

1
2
3
select nom from user1
union
select nom from user2

Miagiste. A la recherche d'un emploi sur Paris (QlikView ou Java). En savoir plus sur moi : https://gokan-ekinci.appspot.com

+0 -0
Auteur du sujet

QuentinC tu as bien compris :

  • user1 = {A, B, C, D, E}
  • user2 = {C, D, E, F, G}

Et je souhaite obtenir {A, B, F, G}.

Union exclusif

Toutefois j'ai essayer ta requête mais elle ne retourne que {A, B}. Ta requête ressemblerai à ceci :

Difference

Gugelhupf effectivement ta requête est équivalente à un union.

EDIT : Je crois que j'ai trouver une requête, elle me retourne effectivement {A, B, F, G}

1
2
3
SELECT nom FROM user1 WHERE nom NOT IN (SELECT nom FROM user2)
UNION
SELECT nom FROM user2 WHERE nom NOT IN (SELECT nom FROM user1);

Requête équivalente :

1
2
3
SELECT nom FROM user1 WHERE NOT EXISTS (SELECT nom FROM user2 WHERE user1.nom = user2.nom)
UNION
SELECT nom FROM user2 WHERE NOT EXISTS (SELECT nom FROM user1 WHERE user1.nom = user2.nom);

Y a t-il une autre manière de faire ? Ou sinon laquelle des deux est plus efficace ?

Édité par john.doe

+0 -0

Efficace ou pas je ne sais pas, mais par rapport à ton besoin exprimé il existe une autre solution :

1
2
3
4
5
SELECT COALESCE(T1.nom, T2.nom) AS nom
FROM user1 T1
FULL JOIN user2 T2
ON T1.nom = T2.nom
WHERE T1.nom IS NULL OR T2.nom IS NULL;

EDIT : Et encore une autre (plus couteuse) :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
(
    SELECT T1.nom FROM user1 T1
    EXCEPT
    SELECT T2.nom FROM user2 T2
)
UNION ALL
(
    SELECT T2.nom FROM user2 T2
    EXCEPT
    SELECT T1.nom FROM user1 T1
)

Édité par Gugelhupf

Miagiste. A la recherche d'un emploi sur Paris (QlikView ou Java). En savoir plus sur moi : https://gokan-ekinci.appspot.com

+1 -0

Toutefois j'ai essayer ta requête mais elle ne retourne que {A, B}.

J'avais fait la remarque juste en-dessous, pour te permettre d'arriver à la variante not exists que tu as trouvée par toi-même ensuite.

Tiens, le mot-clé intersect, je ne connaissais pas. ca existe avec MySQL 5.5 ?

Bien joué pour la variante coalesce. Mais je suis d'avis que ça sera très lent.

Un bencmark opposant toutes les solutions serait intéressant. Perso je parie pour la version not exists… mais avec MySQL, pas sûr, certaines requêtes plutôt simples sont inexpliquablement lentes parfois.

Ma plateforme avec 23 jeux de société classiques en 6 langues et 13000 joueurs: http://qcsalon.net/ | Apprenez à faire des sites web accessibles http://www.openweb.eu.org/

+0 -0

Bien joué pour la variante coalesce. Mais je suis d'avis que ça sera très lent.

Un bencmark opposant toutes les solutions serait intéressant. Perso je parie pour la version not exists… mais avec MySQL, pas sûr, certaines requêtes plutôt simples sont inexpliquablement lentes parfois.

QuentinC

Merci :) La variante avec COALESCE est beaucoup plus rapide que la solution avec EXCEPT d'après le plan d'exécution.

Je suis chaud pour faire un benchmark, ce week-end peut-être… ? :P Quels sont les requêtes que vous souhaiteriez-voir mis à part les 2 derniers que j'ai écrit ?

Miagiste. A la recherche d'un emploi sur Paris (QlikView ou Java). En savoir plus sur moi : https://gokan-ekinci.appspot.com

+0 -0
Auteur du sujet

J'avais fait la remarque juste en-dessous, pour te permettre d'arriver à la variante not exists que tu as trouvée par toi-même ensuite.

Oui et merci soit dit en passant ^^

Tiens, le mot-clé intersect, je ne connaissais pas. ca existe avec MySQL 5.5 ?

Je suis en 5.6 et malheureusement toujours pas de INTERSECT

Quels sont les requêtes que vous souhaiteriez-voir mis à part les 2 derniers que j'ai écrit ?

Ça serait intéressant d'ajouter le NOT IN et le NOT EXISTS

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte