Probleme avec requete sql NOT EXISTS et NOT IN

Probleme avec requete sql NOT EXISTS et NOT IN - SQL/NoSQL - Programmation

Marsh Posté le 21-06-2010 à 14:29:27    

Bonjour,
 
Je reviens sur le forum pour avoir un peu d'aide. J'ai un petit problème avec ma requête sql avec laquelle j'utilise comme contrainte NOT EXISTS ou not in.
 
En fait, j'ai une table contenant toutes les valeurs (table Stock) et une autre table contenant une partie des valeurs (table Stock2) de la précédente table. Mon but est d'afficher toutes les valeurs qui ne sont pas contenues dans la seconde table Stock2. En gros, je voudrais afficher tous les libellés = 'lost' qui ne sont pas dans Stock2 et qui ont donc un numéro différent de Stock.
 
Table Stock
Libelle | numero
lost    | 1
lost    | 30
toto   | 2
lost    | 30
alpha  |19
alpha  | 20
lost    | 15
 
Table Stock2
Libelle | numero
lost    | 1
lost    | 25
alpha  | 19
 
J'ai essayé de faire ça plusieurs façons mais sans succés:
 

Code :
  1. SELECT  *
  2. FROM Stock
  3. WHERE 
  4. Stock.[numero]=
  5. NOT EXISTS
  6. (SELECT distinct * 
  7. FROM T_Stock
  8. );


 
Ca me retourne rien  :(  
 
de même si je rajoute le libellé comme contrainte supplémentaire
 
select distinct * from Stock
where
Stock.[libelle] = 'lost' and
Stock.numero = not exists (select distinct * from Stock2 where Stock2.[libelle]='lost');
 
J'ai essayé avec la clause not in :
 
SELECT * from Stock
WHERE
Stock.libelle = 'lost'  
AND  
Stock.numero
NOT IN
(
SELECT Stock2.numero from Stock2 where Stock2.libelle = 'lost');
 
avec cette dernière ça me sort une liste abominable et qui est fausse  :( .
 
Si quelqu'un peut m'aider.
Merci.

Reply

Marsh Posté le 21-06-2010 à 14:29:27   

Reply

Marsh Posté le 21-06-2010 à 15:43:11    

Tu as besoin d'utiliser un Left Join pour ca:

Code :
  1. SELECT a.*
  2. FROM Stock a
  3. LEFT JOIN Stock2 b ON b.libelle = a.libelle AND b.numero = a.numero
  4. WHERE b.libelle IS NULL


 
Cette requete te retournera tous les enregistrement present dans Stock mais pas dans Stock2.

Reply

Marsh Posté le 21-06-2010 à 16:09:42    

 
MINUS répond aussi à la problématique, aux valeurs distinctes près ( ==> le tuple  ('lost',30) n'est retourné qu'une fois) :
select * from stock minus select * from stock2
 
Par contre ta requete avec le NOT IN est bonne pour moi, si tu ne t'intéresses qu'au libellé 'lost'. Bizarre donc qu'elle ne te retourne pas ce qui t'intéresse...

Reply

Marsh Posté le 21-06-2010 à 16:15:29    

Bonjour Oliii,
 
Merci pour ta réponse. Juste quelques questions :  
 
Peut on rajouter dans la requete une troisième table Stock3 qui contient elle aussi une partie des valeurs de la table Stock ?
 
j'ai testé ta requête, par contre, il y a un truc que je n'arrive pas à comprendre : dans Stock j'ai 1876 ressources dont le libellé est 'lost', dans Stock2 j'ai 1454 ressources identiques à Stock avec le libellé 'lost' et dans Stock3 j'ai 44 ressources identiques à Stock pour le libellé 'lost', ce qui fait un total de 1498 ressources identiques à Stock. Il reste donc 378 ressources 'lost' qui ne sont ni dans Stock2 ni dans Stock3.
 
Quand j'execute ta requête : j'arrive au résultat de 605 ressources 'lost' de Stock qui ne sont pas dans Stock2 et Stock3 au lieu des 378.
 
Au sinon, j'avais essayé ce style de requête :
 

Code :
  1. SELECT *
  2. FROM Stock
  3. WHERE Stock.libelle = 'lost'
  4. AND
  5. NOT EXISTS (
  6.   SELECT *
  7.   FROM Stock2
  8.   WHERE Stock.libelle = Stock2.libelle
  9.    AND Stock.numero = Stock2.numero
  10. );


 
Mais bon j'arrive aussi avec 605 ressources  :( .

Reply

Marsh Posté le 21-06-2010 à 16:31:10    


tu es sûr de ne pas avoir de doublons ('lost',xx) dans stock2, voire dans stock3 ?
ca expliquerait le différentiel

Reply

Marsh Posté le 21-06-2010 à 16:47:00    

Salut jielbi,
 
Pour ma requete not in, tu as raison, elle marche dès que je rajoute un distinct :
 

Code :
  1. SELECT distinct * from Stock
  2. WHERE
  3. Stock.libelle = 'lost' 
  4. AND 
  5. Stock.numero
  6. NOT IN
  7. (
  8. SELECT Stock2.numero from Stock2 where Stock2.libelle = 'lost');


 
ça me renvoi le même nombre 605 que la requête d'Oliii. Par contre, ta requête avec minus ne marche pas chez moi, c'est peut être parce que je suis sous ACCESS.
 
Au sinon, je suis pratiquement sur que Stock2 ne contient pas de doublon. Comment puis je le vérifier ?

Reply

Marsh Posté le 21-06-2010 à 16:58:16    


pour vérifier tes doublons:
 
select libelle,numero,count(*) from stock2 having count(*) >1 group by libelle,numero
 
ceci étant, je connais mal access...

Reply

Marsh Posté le 21-06-2010 à 17:01:28    

Ah, avec Access. Mais avec ODBC, ou autre, ou directement en VBA ou en requête interne ? La syntaxe n'est pas la même.
 
En VBA, ou avec les requetes internes à Access, les chaines de caractères sont entourées par des guillemets (" ), et pas par des simples apostrophes ('). Par contre avec une couche ODBC ou autre, c'est avec des apostrophes.
 
Au lieu de

SELECT  *
FROM Stock
WHERE  
Stock.[numero]=
NOT EXISTS
(SELECT distinct *  
FROM T_Stock
);


Essayer avec

SELECT  *
  FROM Stock
 WHERE  
       Stock.numero NOT IN
       (SELECT Stock2.numero
          FROM Stock2
         WHERE Stock2.libelle = Stock.libelle
       );


Message édité par olivthill le 21-06-2010 à 17:04:20
Reply

Marsh Posté le 21-06-2010 à 17:26:47    

Pour la recherche de doublons, la requête ne marche pas sous ACCESS, mais si je fais un select distinct j'élimine les doublons. En faisant ça je n'ai pas de doublons dans ma table stock2.
 
Ce que je ne comprends pas le nombre de ressources qui m'apparait lorsque j'execute la requete NOT IN.

Reply

Marsh Posté le 22-06-2010 à 08:25:28    

Mieux vaut eviter les NOT IN, il va faire un table scan de Stock2 pour chaque enregistrement de Stock.
Avec un Join il va faire un Select sur les 2 tables une seule fois et faire la comparaison en memoire.
 
Tu ne vois peut etre pas la difference sur si peu d'enregistrement mais c'est une mauvaise habitude a perdre :)

Reply

Marsh Posté le 22-06-2010 à 08:25:28   

Reply

Marsh Posté le 22-06-2010 à 09:33:09    

Bien sûr qu'il vaut mieux faire des jointures que des sous-requêtes, mais c'est nécessaire ici. Pas la peine de donner des leçons quand on lit mal la question initiale.

Reply

Marsh Posté le 22-06-2010 à 09:34:26    

Salut Oliii,
 
En fait, je m'en suis rendu compte, ta requête est bien plus performante en temps d'execution. Par contre, j'ai essayé de faire la chose suivante, c'est à dire, rechercher les élements qui sont en communs avec la table Stock dans Stock2 et Stock3, en faisant :
 
   

Code :
  1. SELECT a.*
  2.    FROM Stock a
  3.    LEFT JOIN Stock2 b ON b.libelle = a.libelle AND b.numero = a.numero
  4.    WHERE b.libelle IS NULL
  5.    UNION
  6.    SELECT c.*
  7.    FROM Stock c
  8.    LEFT JOIN Stock3 d ON d.libelle = c.libelle AND d.numero = c.numero
  9.    WHERE d.libelle IS NULL


 
Cette requête te semble elle correcte ?

Reply

Marsh Posté le 22-06-2010 à 11:33:45    

Tu peux faire ca comme ca:

Code :
  1. SELECT a.*
  2. FROM Stock a
  3.     LEFT JOIN Stock2 b ON b.libelle = a.libelle AND b.numero = a.numero
  4.     LEFT JOIN Stock3 c ON c.libelle = a.libelle AND c.numero = a.numero
  5. WHERE b.libelle IS NULL
  6.     AND c.libelle IS NULL


 

olivthill a écrit :

Bien sûr qu'il vaut mieux faire des jointures que des sous-requêtes, mais c'est nécessaire ici. Pas la peine de donner des leçons quand on lit mal la question initiale.


En quoi est-ce que j'ai mal compris la question?

Reply

Marsh Posté le 02-07-2010 à 15:52:25    

EDIT: post inutile, pas vu que MINUS avait déjà été évoqué


Message édité par tilolebo le 02-07-2010 à 15:54:22

---------------
Ravèt pa janmen ni rézon douvan poul
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed