Elimination des doublons d'un Select sur 4 tables

Elimination des doublons d'un Select sur 4 tables - SQL/NoSQL - Programmation

Marsh Posté le 03-10-2007 à 08:47:08    

Bonjour tout le monde.

 

Voila a l'issus d'un développement en VB.net avec données stockée en BDD (SQL Server) je reste bloqué sur une requete. Je dois affiché des informations qui sont issus de 4 tables différentes. Jusque la tout va bien SELECT et WHERE sont de la partie.
Mais malheureusement je réupère des doublons :(
Alors j'ai fait un SELECT DISCTINCT mais il m'efface pas les doublons il me les classes (bizarre) surement le fait que je fait appel a 4 tables différentes.

 

Voila la requete actuelle

 
Code :
  1. SELECT
  2.       nom_sta, prenom_sta, nom_session, nom_ent, dept_ent, type_contrat, date_entree
  3. FROM
  4.       STAGIAIRE, SESSION, ENTREPRISE, RELATION
  5. WHERE
  6.       SESSION.id_session = STAGIAIRE.id_session AND
  7.       RELATION.id_ent = ENTREPRISE.id_ent AND
  8.       RELATION.id_sta = STAGIAIRE.id_stag
 

ce qui donne

 
Citation :


Nom           Prenom       Session      Entreprise         dept          Contrat       date entréé
TOTO        *******     ******     ********         76               CDI            **/**/**  
*****      *******     ******     ********         14               CDF            **/**/**  
*****      *******     ******     ********         27               CDI            **/**/**  
TOTO       *******     ******     ********         61               CDD           **/**/**  

 

Comme vous pouvez le voir j'en es fait exprès de mettre un doublon.

 

Si je rajoute un DISCTINCT apres le selent voici ce qui me sort

Citation :


Nom           Prenom       Session      Entreprise         dept          Contrat       date entréé
*****      *******     ******     ********         14               CDF            **/**/**  
*****      *******     ******     ********         27               CDI            **/**/**  
TOTO       *******     ******     ********         61               CDD           **/**/**  
TOTO        *******     ******     ********         76               CDI            **/**/**    

 

humm pas génial tout ca.

 

Donc en gros ce que je souhaite c'est pouvoir sortir la meme liste mais en ayant qu'une seule et unique fois 1 personne, et cela pour condition la date d'entréen (en entreprise) la plus recente

 

pour info
nom et prénom font partie de la table stagiaire
session fait partie de la table session
entreprise et département fait partie de la entreprise
contrat et date d'entrée fait partie de la table relation

 

Voila

 

merci par avance


Message édité par hyptnos le 03-10-2007 à 08:48:28
Reply

Marsh Posté le 03-10-2007 à 08:47:08   

Reply

Marsh Posté le 03-10-2007 à 09:01:25    

normal que ça sorte deux lignes, les informations sont complétements différentes entre les deux lignes: pas le même dpt et pas le même type de contrat.
Si tu veux uniquement le stagiaire avec la plus petite date d'entrée il faut utiliser la fonction d'aggregation min + une clause group by.
Mais tu vas vite te rendre compte que ça ne résoud que la moitié de ton problème dans la mesure ou tu as toujours la même problèmatique sur dept/type contrat.
 
 
Note: en cherchant un peu tu aurais trouvé 400 topics sur le sujet des doublons qui répondaient à ton problème.

Reply

Marsh Posté le 03-10-2007 à 09:10:45    

La jointure me semble suspecte en plus... Tu veux pas en faire une propre?

Reply

Marsh Posté le 03-10-2007 à 09:18:37    

Bas le souci que j'ai déja essayé le group by mais sa ne va pas du tout du tout plein d'erreur.

 

En gros j'ai penser faire un DISTINCT de la base RELATION (puisqu'elle contient l'id du stagiaire et l'id de l'entreprise + les dates)
stocké le resultat dans une table temporaire et faire le Select avec les clauses Where ensuite

 

Qu'en pensez vous ?

 

cela je sèche sur la syntaxe la :S

 
leflos5 a écrit :

La jointure me semble suspecte en plus... Tu veux pas en faire une propre?


C'est a dire ???? suspecte dans quel sens ?

Message cité 1 fois
Message édité par hyptnos le 03-10-2007 à 09:20:23
Reply

Marsh Posté le 03-10-2007 à 09:36:05    

hyptnos a écrit :

Bas le souci que j'ai déja essayé le group by mais sa ne va pas du tout du tout plein d'erreur.


mais bien sur, ça doit être la faute du GROUP BY [:w3c compliant][:w3c compliant][:w3c compliant]

hyptnos a écrit :

En gros j'ai penser faire un DISTINCT de la base RELATION (puisqu'elle contient l'id du stagiaire et l'id de l'entreprise + les dates)
stocké le resultat dans une table temporaire et faire le Select avec les clauses Where ensuite
Qu'en pensez vous ?


que ça résoudra pas ton problème, tu dois récupérer la plus petite date d'entrée et sans aggrégation tu n'y arriveras pas

hyptnos a écrit :


C'est a dire ???? suspecte dans quel sens ?


Certaines habitudes veulent que l'on écrive les jointures explicitement, quelque chose dans le genre:

Code :
  1. SELECT
  2.           nom_sta, prenom_sta, nom_session, nom_ent, dept_ent, type_contrat, date_entree
  3.      FROM
  4.                              STAGIAIRE
  5.  INNER JOIN             SESSION      ON SESSION.id_session = STAGIAIRE.id_session
  6.  INNER JOIN             RELATION     ON RELATION.id_sta = STAGIAIRE.id_stag
  7.  INNER JOIN             ENTREPRISE ON ENTREPRISE.id_ent  = RELATION.id_ent
 

Et pour ton problème je te le redis tu vas avoir besoin d'un min et ça ne sera pas suffisant.
Il va te falloir faire un truc dans le genre:

Code :
  1. SELECT
  2.           nom_sta, prenom_sta, nom_session, nom_ent, dept_ent, type_contrat, date_entree
  3.      FROM
  4.                              STAGIAIRE S1
  5.  INNER JOIN             SESSION      ON SESSION.id_session = STAGIAIRE.id_session
  6.  INNER JOIN             RELATION     ON RELATION.id_sta = STAGIAIRE.id_stag
  7.  INNER JOIN             ENTREPRISE ON ENTREPRISE.id_ent  = RELATION.id_ent
  8. WHERE
  9.   EXISTS (
  10.     SELECT
  11.       S2.nom_sta, S2.prenom_sta, min(S2.date_entree)
  12.     FROM
  13.       STAGIAIRE S2  
  14.     WHERE
  15.       S2.nom_sta=S1.nom_sta AND  S2.prenom_sta = S1.prenom_sta
  16.     GROUP BY S2.nom_sta, S2.prenom_sta
  17.     HAVING min(S2.date_entree)=S1.date_entree
  18.   )


voila une bonne solution toute faite, mais je suis plus que dubitatif sur l'interêt pédagogique de la chose.


Message édité par anapajari le 03-10-2007 à 09:37:30
Reply

Marsh Posté le 03-10-2007 à 09:41:47    

pour ta jointure, oublie la remarque de leflos5. il est pas réveillé, elle est bonne (mais mal écrite et effectivement pas pratique à lire)
 
pour le reste du problème, avant d'aller plus loin, est-ce que tu peux faire juste un petit truc ?
 

Code :
  1. SELECT count(nom_sta + prenom_sta) total1, count(DISTINCT nom_sta + prenom_sta) total2
  2. FROM stagiaire


 
Avant de parler de doublons, faudrait déjà que tu sois sûr qu'il n'y a pas d'homonymes dans ta base.
Si les deux totaux ne sont pas égaux, c'est que tu en as (c'est à dire qu'un Georges Dupont habite à Paris, et un autre Georges Dupont habite à Marseille).
 
Ensuite, dans ta requête actuelle, tu peux ajouter le champ "stag_id" histoire de vérifier aussi quels sont les vrais "doublons" et quels sont les homonymes (deux fois le même ID et c'est effectivement un "doublon", sinon c'est simplement un homonyme -ou pollution de ta base de données-)
 
Pour le reste, +1 de ce qu'a dit Anapajari : j'ai déjà passé 2 heures à repondre à une question identique pas plus tard qu'hier, en expliquant la démarche étape par étape.

Reply

Marsh Posté le 03-10-2007 à 09:48:46    

Merci je comprend a peut pret la chose
 
Du moins sur les jointures en effet c'est plus explicite et plus propre
 
Mais la j'ai une erreur au test de la requete :S
 

Citation :


Serveur : Msg 107, Niveau 16, État 3, Ligne 1
Le préfixe de colonne 'STAGIAIRE' ne correspond ni au nom de table ni au nom d'alias utilisés dans la requête.
Serveur : Msg 107, Niveau 16, État 1, Ligne 1
Le préfixe de colonne 'STAGIAIRE' ne correspond ni au nom de table ni au nom d'alias utilisés dans la requête.
 


 
j'ai vérifier tout les champs etc... je vois pas ce qui cloche

Reply

Marsh Posté le 03-10-2007 à 09:50:36    

MagicBuzz a écrit :

pour ta jointure, oublie la remarque de leflos5. il est pas réveillé, elle est bonne (mais mal écrite et effectivement pas pratique à lire)
 
pour le reste du problème, avant d'aller plus loin, est-ce que tu peux faire juste un petit truc ?
 

Code :
  1. SELECT count(nom_sta + prenom_sta) total1, count(DISTINCT nom_sta + prenom_sta) total2
  2. FROM stagiaire


 
Avant de parler de doublons, faudrait déjà que tu sois sûr qu'il n'y a pas d'homonymes dans ta base.
Si les deux totaux ne sont pas égaux, c'est que tu en as (c'est à dire qu'un Georges Dupont habite à Paris, et un autre Georges Dupont habite à Marseille).
 
Ensuite, dans ta requête actuelle, tu peux ajouter le champ "stag_id" histoire de vérifier aussi quels sont les vrais "doublons" et quels sont les homonymes (deux fois le même ID et c'est effectivement un "doublon", sinon c'est simplement un homonyme -ou pollution de ta base de données-)
 
Pour le reste, +1 de ce qu'a dit Anapajari : j'ai déjà passé 2 heures à repondre à une question identique pas plus tard qu'hier, en expliquant la démarche étape par étape.


 
Les deux valeur sont identiques donc je pense que c'est une premiere chose de positive non?

Reply

Marsh Posté le 03-10-2007 à 10:01:14    

positive, oui et non.
 
apparement, t'as effectivement pas d'homonyme.
 
donc ton TOTO qui a fait un CDI dans le 76 et un CDD dans le 61 semblerait être la même personne (bon, y'a d'autres vérifications à faire mais déjà là c'est bien parti)
 
pour le reste, t'as plus qu'à partir de la requête qu'à proposer Anajapari, ou une de celles que j'ai proposé dans un autre topic hier afin de ne conserver que le dernier des contrats de tes stagiaires.

Reply

Marsh Posté le 03-10-2007 à 10:13:41    

Bon en fait je me galère pour rien :p
 
J'ai oublié de précisé que j'ai un champs date_sortie dans la table relation. Qui est a NULL si  le stagiaire en question est toujours dans l'entreprise
 
Ce qui fait que cela simplifie considérablement la chose en rajoutant dans la close where de ma requete iniatial " RELATION.date_sortie IS NULL "
 
Voici la requete fonctionnelle :)
 
Merci en tout cas d'avoir pris le temps de m'avoir aider :)
 

Code :
  1. select
  2.    nom_sta, prenom_sta, nom_session, nom_ent, dept_ent, type_contrat, date_entree
  3. from
  4.    STAGIAIRE, SESSION, ENTREPRISE, RELATION
  5. where
  6.    SESSION.id_session = STAGIAIRE.id_session AND
  7.    RELATION.id_ent = ENTREPRISE.id_ent AND
  8.    RELATION.id_sta = STAGIAIRE.id_stag AND
  9.    RELATION.date_sortie IS NULL


Reply

Marsh Posté le 03-10-2007 à 10:13:41   

Reply

Marsh Posté le 03-10-2007 à 10:18:58    

ah ben oui, si t'as un moyen simple pour éliminer les doublons... :D

Reply

Marsh Posté le 03-10-2007 à 11:08:17    

Heu juste un autre petit truc lol
Histoire de perfectionner un peu mon programme.
 
En effet je definit le type de contrat (CDD, CDI, etc..) dans l'ajout d'une relation. Or un CDI sa date de fin de contrat est définit ce qui fait qu'avec ma tel requete rien ne s'affichera pour un CDD
Donc faut que je puisse comparer le champs date_sortie de la table RELATION avec la date courante.
 
il me semble que en Sql l'appel a la date courrante est : CURRENT_DATE() ou DATE()
 
mais marche pas :(
 
je fait un  
 
AND RELATION.date_sortie >= CURRENT_DATE()
 
mais non rien marche il me met
 

Citation :


Serveur : Msg 156, Niveau 15, État 1, Ligne 6
Syntaxe incorrecte vers le mot clé 'CURRENT_DATE'.


 
une idée ?

Reply

Marsh Posté le 03-10-2007 à 11:09:56    

dbo.GetDate() ça ira mieux je pense

Reply

Marsh Posté le 03-10-2007 à 11:14:18    

Arf oui j'avais pas pensé au objet commun.

 

Cela dit il me retourn

 
Citation :


Serveur : Msg 208, Niveau 16, État 1, Ligne 1
'dbo.GetDate' : nom d'objet incorrect.

 

Cependant si je fais dans l'analyseur de requete un

 
Code :
  1. select getDate()
 

il me retourne bien la date courante

 

Donc au final je fait

 
Code :
  1. select
  2.    nom_sta, prenom_sta, nom_session, nom_ent, dept_ent, type_contrat, date_entree , date_sortie, getdate() As DT
  3. from
  4.    STAGIAIRE, SESSION, ENTREPRISE, RELATION
  5. where
  6.    SESSION.id_session = STAGIAIRE.id_session AND RELATION.id_ent = ENTREPRISE.id_ent AND RELATION.id_sta = STAGIAIRE.id_stag and RELATION.date_sortie is NULL AND RELATION.date_sortie >= DT
 

mais il me sort

 
Citation :


Serveur : Msg 207, Niveau 16, État 3, Ligne 1
'DT' : nom de colonne incorrect.

 

grrrr vais pas y arriver


Message édité par hyptnos le 03-10-2007 à 11:35:36
Reply

Marsh Posté le 03-10-2007 à 11:49:00    

nan mais pourquoi tu colles ton getdate dans ton select :o
 
c'est juste pour remplacer ton current_date
 
et c'est normal que tu ne puisses pas atteindre un alias de champ dans ta clause where

Reply

Marsh Posté le 03-10-2007 à 11:57:19    

Code :
  1. select
  2.    nom_sta, prenom_sta, nom_session, nom_ent, dept_ent, type_contrat, date_entree , date_sortie
  3. from
  4.    STAGIAIRE, SESSION, ENTREPRISE, RELATION
  5. where
  6.    SESSION.id_session = STAGIAIRE.id_session AND
  7.    RELATION.id_ent = ENTREPRISE.id_ent AND
  8.    RELATION.id_sta = STAGIAIRE.id_stag and
  9.    (RELATION.date_sortie is NULL or RELATION.date_sortie > getdate() )
 

Voila ca roule pfiou c'etait laborieux ^^

 

Enfin le principal c'est que cela fonctionne :p

 

Merci encore


Message édité par hyptnos le 03-10-2007 à 11:57:56
Reply

Marsh Posté le 05-10-2007 à 22:27:02    

Je maintiens qu'une jointure ne devrait pas se faire comme ça :o
 
Et non je crois pas qu'en programmation le principal soit que ça fonctionne :o

Reply

Sujets relatifs:

Leave a Replay

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