[SQL] SQL Server 2000 & la différence (not exists)

SQL Server 2000 & la différence (not exists) [SQL] - SQL/NoSQL - Programmation

Marsh Posté le 18-02-2009 à 17:24:44    

Bonjour,  
 
J'ai deux tables :
 
personnes (idpers, nom_pers, prenom, projid, etc.)
projets(projid, nom_proj, type, directeur, etc.)
 
Je veux sortir la liste de toutes les personnes qui ne sont pas affectés sur les projets de type 'maintenance'.
 
Je voulais faire un except , jusqu'à ce que je trouve que ça n'existe pas sous sql2000.
Donc  je passe par 'not exists' , j'ai donc écrit  (en m'inspirant de l'aide microsoft):
 
select distinct nom_pers
 from personnes
 where not exists
(select * from projets
 where projets.proj_id = personnes.proj_id
 and projet_type  like '%maintenance%' ) ;
 
ça ne semble pas être ça puisqu'il me sort presqu'autant de noms que si je faisais une jointure classique select * from personnes, projet where projets.proj_id = personnes.proj_id ;
Et que surtout quand je vérifie sur certains noms ils sont quand meme affectés sur les projets maintenance.
 
J'ai besoin d'une lumière pour m'éclairer.
 
merci de m'aider  
 
un noob

Reply

Marsh Posté le 18-02-2009 à 17:24:44   

Reply

Marsh Posté le 19-02-2009 à 09:34:38    


 
Salut,  
 
select  
        personnes.nom_pers  
from  
        personnes  
where  
        (personnes.projid not in (select projets.projid from projets  
                                          where projet_type  like '%maintenance%'))
 
?


Message édité par THX le 19-02-2009 à 09:37:47
Reply

Marsh Posté le 19-02-2009 à 10:20:25    

Bonjour et merci pour cette réponse ,  
 
Cette requête fonctionne mais j'ai le même problème, elle me sort des noms qui sont quand même affectés à des projets maintenance. Du coup j'ai presque autant de lignes de résultats que si je ne triais pas.
Quelqu'un sait d'où est ce que ça peut venir ?

Reply

Marsh Posté le 19-02-2009 à 10:33:22    

Euh les noms que la requête sort sont des noms qui sont affectés à des projets maintenance ET d'autres projets ?

Reply

Marsh Posté le 19-02-2009 à 10:51:10    

oui je viens de vérifier


Message édité par mounen le 19-02-2009 à 10:51:41
Reply

Marsh Posté le 19-02-2009 à 11:26:50    

Admettons que tu es un "Dupond Pierre" qui est affecté à 3 projets, tu as 3 entrées dans ta table personnes pour ce Dupond Pierre ?
 
Il ne devrait y avoir qu'une seule et unique entrée par personne ;).  
 
Ensuite une table de liaison idpers / projid ou je n'ai peut-etre pas compris.


Message édité par THX le 19-02-2009 à 11:35:17
Reply

Marsh Posté le 19-02-2009 à 11:45:02    

tu as très bien compris. Et c'est ce qui m'a frappé quand j'ai commencé à travailler sur cette base de données.
Bon ben reste plus qu'a convaincre l'admin...
 
Merci quand même

Reply

Marsh Posté le 19-02-2009 à 13:26:43    

ça vous amuse de foutre par terre votre serveur quand une simple jointure résoud le problème sans effort ?

 
Code :
  1. SELECT per.*
  2. FROM personnes per
  3. LEFT OUTER JOIN projets pro ON pro.projid = per.projid AND pro.type = 'Maintenance'
  4. WHERE pro.projid IS NULL


Message édité par MagicBuzz le 19-02-2009 à 13:27:01
Reply

Marsh Posté le 19-02-2009 à 13:52:48    

Ca ne résoudra pas son problème ;)
 
Mais ce n'est pas grave.
 
 
 

Reply

Marsh Posté le 19-02-2009 à 14:12:30    

Merci magicbuzz mais j'ai le même résultat qu'avant...

Reply

Marsh Posté le 19-02-2009 à 14:12:30   

Reply

Marsh Posté le 19-02-2009 à 14:20:06    

Moi c'était juste histoire de virer déjà cette sous-requête inutile :o

 

Ensuite, les noms des gens qui sont en double selon s'ils sont sur 1 ou n projets, y'a un souci de modélisation là... Parce que c'est total nawak. idpers doit être la PK de la table personnes (et nom_pers, prenome) à priori une clé alternative, tout du moins sans doublons réels, uniquement des homonymes), et si une personne peut travailler sur plusieurs projets, et un projet peut être efectué par plusieurs personnes, alors il faut une table de correspondance.

 

Finalement, voilà la solution au problème : (avec toujours une jointure, ça sert à rien de se lancer dans des sous-select inutiles)

Code :
  1. SELECT per.nom_pers, per.prenom
  2. FROM personnes per
  3. LEFT OUTER JOIN projets pro ON pro.projid = per.projid AND pro.type = 'maintenance'
  4. GROUP BY per.nom_pers, per.prenom
  5. HAVING count(pro.projid) = 0
 

Vérification :

 
Code :
  1. DROP TABLE personnes
  2. go
  3. DROP TABLE projets
  4. go
  5.  
  6. CREATE TABLE projets
  7. (
  8.     projid numeric PRIMARY KEY,
  9.     nom_proj varchar(20),
  10.     type varchar(20),
  11.     directeur varchar(20)
  12. )
  13. go
  14.  
  15. CREATE TABLE personnes
  16. (
  17.     idpers numeric,
  18.     nom_pers varchar(20),
  19.     prenom varchar(20),
  20.     projid numeric FOREIGN KEY REFERENCES projets(projid)
  21. )
  22. go
  23.  
  24. INSERT INTO projets VALUES (1, 'Projet 1', 'maintenance', 'Directeur');
  25. INSERT INTO projets VALUES (2, 'Projet 2', 'maintenance', 'Directeur');
  26. INSERT INTO projets VALUES (3, 'Projet 3', 'maintenance', 'Directeur');
  27. INSERT INTO projets VALUES (4, 'Projet 4', 'nettoyage', 'Directeur');
  28. INSERT INTO projets VALUES (5, 'Projet 5', 'nettoyage', 'Directeur');
  29. INSERT INTO projets VALUES (6, 'Projet 6', 'nettoyage', 'Directeur');
  30.  
  31. INSERT INTO personnes VALUES (1, 'Dupond', 'Toto', 1);
  32. INSERT INTO personnes VALUES (2, 'Dupond', 'Toto', 2);
  33. INSERT INTO personnes VALUES (3, 'Durand', 'Titi', 3);
  34. INSERT INTO personnes VALUES (4, 'Durand', 'Titi', 4);
  35. INSERT INTO personnes VALUES (5, 'Dupuis', 'Tutu', 5);
  36. INSERT INTO personnes VALUES (6, 'Dupuis', 'Tutu', 6);
  37. INSERT INTO personnes VALUES (7, 'Dupuis', 'Tutu', NULL);
  38. INSERT INTO personnes VALUES (8, 'Prout', 'Coin', NULL);
  39. INSERT INTO personnes VALUES (7, 'Dupond', 'Toto', NULL);
  40. INSERT INTO personnes VALUES (7, 'Durand', 'Titi', NULL);
  41.  
  42. SELECT per.nom_pers, per.prenom
  43. FROM personnes per
  44. LEFT OUTER JOIN projets pro ON pro.projid = per.projid AND pro.type = 'maintenance'
  45. GROUP BY per.nom_pers, per.prenom
  46. HAVING count(pro.projid) = 0
 
 

(1 row(s) affected)

 

(1 row(s) affected)

 

(1 row(s) affected)

 

(1 row(s) affected)

 

(1 row(s) affected)

 

(1 row(s) affected)

 

(1 row(s) affected)

 

(1 row(s) affected)

 

(1 row(s) affected)

 

(1 row(s) affected)

 

(1 row(s) affected)

 

(1 row(s) affected)

 

(1 row(s) affected)

 

(1 row(s) affected)

 

(1 row(s) affected)

 

(1 row(s) affected)
nom_pers             prenom
-------------------- --------------------
Prout                Coin
Dupuis               Tutu
Warning: Null value is eliminated by an aggregate or other SET operation.

 

(2 row(s) affected)

 
 

Je ne pense pas avoir oublié de cas


Message édité par MagicBuzz le 19-02-2009 à 14:20:40
Reply

Marsh Posté le 19-02-2009 à 14:22:02    

PS : Je sais pas trop d'où vient ce warning, mais à la base on s'en cogne, ça marche :o

Reply

Marsh Posté le 19-02-2009 à 14:52:22    

Merciiiiiiiiiiii !
 
Ça marche  :D.
Une dernière question, est-ce qu'une mauvaise modélisation d'une base de données peut être source de problèmes de performance ?

Reply

Marsh Posté le 19-02-2009 à 15:01:05    

Euh... Est-ce que si je mets des roues carrées à ma voiture je risque d'avoir des problèmes pour rouler ?

Reply

Marsh Posté le 19-02-2009 à 15:02:22    

Non seulement niveau perfs tu y perds énormément (lire des données inutiles, non indexées) mais en plus en maintenance.

 

Mademoiselle "Céline Dupuis" se marie à monsieur "Mathieu Durand".

 

T'as l'air fin pour changer le nom de la demoiselle. Surtout si elle a un homonyme parfait dans la base déjà... Aucun critère pour les différencier, je dirais que t'es mal ;)


Message édité par MagicBuzz le 19-02-2009 à 15:02:46
Reply

Marsh Posté le 19-02-2009 à 15:09:38    

Ok merci pour vos réponses.

Reply

Sujets relatifs:

Leave a Replay

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