none
extraire les couples sans doublons RRS feed

  • Question

  • Bonjour,

    Le problème paraît simple à résoudre, mais je ne trouve pas la solution.

    Ma table Tmembres contient - entre autre - les champs nomprénom et Conjoint

    Il y a 2 lignes pour chaque couple: la clé de 1ère est Nomprénom, la clé de la 2ème est Conjoint

    je voudrais extraire unitairement chaque couple dans un report par la requête :

    SELECT NomPrénom, conjoint
    FROM Tmembres
    WHERE NOT EXISTS (select * from Tmembres where Nomprénom = Conjoint)
    ORDER BY Nomprénom;

    mais je les retrouve en double.

    Il semble que la condition Not exists ne fonctionne pas !

    Merci pour votre aide.

    lundi 5 décembre 2016 09:37

Toutes les réponses

  • Bonjour,

    Si vous voulez ressortir les conjoints, il faut qu'il y ait une clé qui permette de les isoler.
    Un simple booléan (Champ couple O/N) est à envisager dans votre table.
    La votre requête serait fonctionnelle.

    Là, sur la table actuelle, ce qui vous pénalise, c'est que le nom et le prénom sont dans le même champ et vous vous exposez à la fois des risques de saisie et des erreurs.

    Argy

    mardi 6 décembre 2016 09:24
    Modérateur
  • Bonjour,

    Jusqu'à présent, je me suis satisfait de cette impossibilité d'afficher une ligne unique pour chaque couple, mais ça devient de plus en plus fatigant car il me faut éliminer les doubles manuellement.

    Je ne comprends pas  votre solution d'ajouter un champ booléen O/N.

    Pouvez-vous m'expliquer ?

    PS: je précise que si le 1er champ contient Nom + prénom, le champ "Conjoint" contient aussi Nom + prénom.

    Ce que je voudrais, c'est avoir pour chaque couple, une seule ligne contenant :

    Nom-prénom + Nom-prénom du conjoint + évidemment, les champs communs comme l'adresse.

    merci d'avance pour votre réponse.

    dimanche 4 juin 2017 10:44
  • Bonjour,

    Il est a noter que si une personne de la première colonne est un membre et que son conjoint l'est également, alors effectivement il y a deux lignes :

    1. Marcel DURANT ; Monique DURANT
    2. Monique DURANT ; Marcel  DURANT

    Donc votre requête retournera toujours deux enregistrements.

    Mon idée était de considérer que si votre table contient un conjoint, cela suppose implicitement un couple mais ce n'est pas obligatoire ; et si couple, alors il y a deux membres adhérents mais deux lignes puisque l'un est membre et a pour conjoint l'autre et l'autre est membre et a pour conjoint de l'un...

    Vous pourriez alors ajouter un champ suplémentaire qui spécifier que les deux sont membres :

    N°	NomPrénom	Conjoint	TousDeuxMembres
    1	Marcel DURANT	Monique DURANT	Vrai
    2	Monique DUPONT	Pierre DUPONT	Faux
    3	Patrick DUCRET	Venessa DURIEUX	Vrai
    4	Paul DUBOIS	        	Faux
    5	Marthe VOLLER	Felipe GOUSSET	Faux

    Votre requête serait alors :

    SELECT NomPrénom
    FROM MauriceB77;
    UNION SELECT Conjoint
    FROM MauriceB77
    WHERE TousDeuxMembres = True;
    

    et retournerait :

    Membres
    Marcel DURANT
    Marthe VOLLER
    Monique DUPONT
    Monique DURANT
    Patrick DUCRET
    Paul DUBOIS
    Venessa DURIEUX

    Ce qui correspond à ce que vous attendez, mais exige une modification de structure...


    Argy

    lundi 12 juin 2017 08:16
    Modérateur
  • Bonjour et merci pour votre réponse.

    Ma table contient actuellement:

       membres                    conjoint

    DURAND Monique         DURAND Claude

    DURAND Claude           DURAND Monique

    MARTINS André            MARTINS Brigitte

    MARTINS Brigitte          MARTINS André

    ........

    Je suis obligé d'avoir 2 enregistrements pour chaque couple (1 seul si célibataire) pour établir les statistiques d'activités et les assurances).

    Si je comprends bien, le champ supplémentaire que vous proposez "TousDeuxMembres" serait dans ce cas :

     "vrai" pour le 1er enregistrement du couple et "faux" pour le 2ème ?

    lundi 12 juin 2017 09:17
  • Hum, oui et non...

    Dans la partique ne devriez pas doubler les lignes sous prétexte qu'il y a notion de couple ou alors il faut réviser la structure avec

    • un ID unique pour définir la personne (Nom+ Prénom)
    • un champ Nom+ Prénom
    • un champ IDConjoint (qui peut être NULL)

    Dans ce cas on a comme membres :

    N°	NomPrénom	IDConjoint
    1	Marcel DURANT		6
    2	Monique DUPONT		7
    3	Patrick DUCRET		8
    4	Paul DUBOIS	
    5	Marthe VOLLER		9
    6	Monique DURANT		1
    7	Pierre DUPONT		2
    8	Venessa DURIEUX		3
    9	Felipe GOUSSET		5
    10	Nathalie TUANI	

    où deux membres n'ont pas de conjoint...

    Ce qui donne alors :

    NomPrénom
    Marcel DURANT
    Monique DUPONT
    Patrick DUCRET
    Marthe VOLLER
    Monique DURANT
    Pierre DUPONT
    Venessa DURIEUX
    Felipe GOUSSET

    avec la requête :

    SELECT NomPrénom
    FROM MauriceB77
    WHERE (Nz([IDConjoint],0)<>0);
    


    Argy

    lundi 12 juin 2017 09:50
    Modérateur
  • Pour résumer, le champ ID est défini NumeroAuto

    mais alors, il faut que je rattache manuellement l'idconjoint ?

    lundi 12 juin 2017 10:08
  • Oui, c'est bien ça.

    Enfin dans l'existant... Ensuite dans votre formualire de saisie, vous devrez faire ne sorte que le conjoint puisse être sélectionné à partir d'une liste qui exclura bien évidemment tous les membres qui in déjà un IDConjoint NON NULL et <>.

    Dans ce cas, il faudra voir si un célibataire est à NULL ou à 0 voire -1 ; mais bon, si ledit célibataire trouve sa moitié dans la liste... à étudier ; en tout cas, le principe est celui-là.


    lundi 12 juin 2017 10:14
    Modérateur
  • Merci pour votre réponse, je retiens le principe mais ce n'est pas évident à gérer car il y a aussi des couples non mariés qui n'ont donc pas le même nom et il ne sera pas facile de choisir dans la liste......
    lundi 12 juin 2017 10:24
  • Oui, c'est sûr, mais à ce moment là, il y a aussi les homonymes...

    Donc, la partie saisie doit être bien ficelée. Mais au final, votre problématique sera résolue, non ?


    Argy

    lundi 12 juin 2017 11:57
    Modérateur
  • Bonjour,

    Vous pouvez définir vos tables différemment:

    Faites une table annuaire avec les champs

    index
    Nom
    Prénom

    Par exemple

    0,P, Gérard
    1,P, Monique
    2,B,Alphonse
    3,H,Julien
    4,M,Sophie

    Pour les couples, faites une table COUPLE avec 2 colonnes COL1 et COL2

    0,4
    1,3
    2,-1

    Dans les 2 colonnes on indique l'index de la personne dans l'annuaire,
    Si une personne est célibataire, il y a -1 dans COL2
    Pour éviter les doublons, il faut rentrer le couple une seule fois.

    Par exemple, ici il ne faut pas rentrer 3,1 et 4,0

    Vous faites une requête:

    select * from COUPLE where ((COL1 = 1) or (COL2 = 1))
    vous récupérer
    1,3

    Cordialement
    Gérard

    • Proposé comme réponse GP79 lundi 12 juin 2017 14:52
    lundi 12 juin 2017 12:02
  • Bonjour,

    Finalement, j'ai adopté la solution d'Argy (avoir un champs booléen), Je pensais qu'elle répondait à mon besoin et mes contraintes, mais non, il manque toujours des lignes, notamment lorsque dans un couple un seul est adhérent ou bien s'il y a eu une présélection sur d'autres critères qui fait que si le membre sélecté a la valeur "non" pour "couple" alors, il est ignoré.

    A suivre....


    • Modifié ibowl77 mercredi 14 juin 2017 15:36
    mardi 13 juin 2017 08:27
  • Bonjour,

    Une autre solution, ne nécessitant pas d'intervenir sur la structure des tables, serait de remplacer la clause WHERE existante par une simple comparaison.

    SELECT NomPrénom, conjoint
    FROM Tmembres
    WHERE NomPrénom <= conjoint OR conjoint IS NULL
    ORDER BY Nomprénom;

    Le seul cas un peu tordu serait l'homonymie au sein d'un couple... Cas qui pourrait se produire si les deux s'appellent Claude par exemple, et que la femme a pris le nom de son mari. Dans ce cas, la requête retournera les deux lignes (ou aucun si on remplace l'opérateur <= par <).

    Par contre, pour que la solution fonctionne correctement, il faut impérativement que pour un couple il y ait les deux lignes de présentes. S'il n'y en a qu'une, certaines données risque d'être filtrées. 


    • Modifié François DORIN mardi 13 juin 2017 13:43 précision sur les couples
    mardi 13 juin 2017 13:07
  • bonjour,

    Cette solution me plaisait bien sauf que dans le cas où dans le couple, un seul est adhérent, il ne ressort rien.

    Exemple:

                  nomprénom           conjoint                adhérent

               DUPOND Jean        RICHARD Paule           oui

               RICHARD Paule      DUPOND Jean             non

               LACROIX Pierre      LACROIX Monique       non             

               LACROIX Monique  LACROIX Pierre           oui

             

    avec la condition WHERE  :

    WHERE (NomPrénom <= conjoint OR conjoint IS NULL) AND Adhésion = true

    bonne journée.


    • Modifié ibowl77 mardi 13 juin 2017 14:37
    mardi 13 juin 2017 14:24
  • On peut alors feinter un peu

    SELECT DISTINCT
       CASE WHEN NomPrénom <= conjoint OR conjoint IS NULL THEN NomPrénom ELSE conjoint END AS NomPrénom,
       CASE WHEN NomPrénom <= conjoint OR conjoint IS NULL THEN conjoint ELSE NomPrénom END AS conjoint,
    FROM Tmembres
    ORDER BY Nomprénom;

    En gros, on normalise les données (on impose que NomPrénom soit "plus petit" que "conjoint"), et ensuite on supprime les doublons via DISTINCT.

    Ainsi, cela devrait marcher, que la personne soit célibataire, en couple et que le conjoint soit ou non adhérent.

    mardi 13 juin 2017 14:46
  • Cette syntaxe (operateur absent) ne marche pas dans ma requête ......

    • Modifié ibowl77 mardi 13 juin 2017 15:54
    mardi 13 juin 2017 15:42
  • Bon, en analysant la situation, il s'avère que c'est un petit peu plus compliqué que je ne l'ai décrit.

    Dans le cas simple où j'accède à la table qui contient tous les couples, il n'y a pas trop de problèmes: soit j'ai tout en double soit il en manque un ou deux.

    Où ça se complique c'est lorsque j'ai fait une pré-sélection sur une activité et ma table contient alors souvent 1 seule ligne pour le couple (l'un participe et pas l'autre).

    L'idéal alors serait de pouvoir éliminer les doubles sur l'adresse mail.

    Si j'ai par ex:

    DUPOND Jean        RICHARD Paule           dupond@hotmail.com

    RICHARD Paule      DUPOND Jean             dupond@hotmail.com

    je voudrais pouvoir conserver uniquement soit la 1ère soit le 2ème ligne.

    Ne peut-on repartir d'une requête pour identifier les doubles :

    WHERE (((TmpAdher.[Email_perso]) In (SELECT [Email_perso] FROM [TmpAdher] As Tmp GROUP BY [Email_perso] HAVING Count(*) > 1 )))

    et la modifier pour éliminer les doubles ?
    • Modifié ibowl77 mardi 13 juin 2017 20:21
    mardi 13 juin 2017 17:09
  • Oups, pardon, Access ne supporte pas la syntaxe CASE WHEN. Il faut utiliser IIF

    SELECT DISTINCT
       IIF(NomPrénom <= conjoint OR conjoint IS NULL, NomPrénom, conjoint),
       IIF(NomPrénom <= conjoint OR conjoint IS NULL, conjoint, NomPrénom)
    FROM Tmembres

    mardi 13 juin 2017 21:13
  • bonjour et merci pour votre réponse.

    Cette requête donne effectivement le bon résultat, mais il me faut aussi les autres champs associés aux membres.

    Quelle serait la syntaxe pour ajouter par exemple, l'adresse mail (qui peut être différente pour les 2 du couple, mais je prends indifféremment l'une ou l'autre), l'adresse .....etc ?


    • Modifié ibowl77 mercredi 14 juin 2017 06:56
    mercredi 14 juin 2017 06:54
  • Je pensais avoir trouvé la solution:

    j'ai créé une 1ère requête qui me donne une seule occurrence pour chaque couple:

    SELECT DISTINCT IIf(NomPrénom<=conjoint Or conjoint Is Null,NomPrénom,conjoint) AS Nom1, IIf(NomPrénom<=conjoint Or conjoint Is Null,conjoint,NomPrénom) AS Nom2
    FROM Tmpadher;

    puis une 2ème qui utilise le résultat de la 1ère:

    SELECT RTrim (NomPrénom & " / " & Conjoint) AS Noms, [Email_perso], DateAdhésion, TelMobile AS Tel_mobile, Telfixe AS Tel_Fixe
    FROM tmpadher
    WHERE [Nomprénom] IN
    (SELECT [Nom1] from [Req_doublons] where [Nomprénom] = [Nom1])
    ORDER BY Nomprénom;

    Il manque des lignes.....




    • Modifié ibowl77 mercredi 14 juin 2017 08:05
    mercredi 14 juin 2017 07:51
  • Il manque des lignes sans doute car la clause WHERE est erronée.

    SELECT RTrim (NomPrénom & " / " & Conjoint) AS Noms, [Email_perso], DateAdhésion, TelMobile AS Tel_mobile, Telfixe AS Tel_Fixe
    FROM tmpadher
    WHERE [Nomprénom] IN
    (SELECT [Nom1] from [Req_doublons])
    ORDER BY Nomprénom;

    Le "where [Nomprénom] = [Nom1]" n'a pas à être présent.

    mercredi 14 juin 2017 09:04
  • J'ai enlevé cette clause, mais le résultat est le même, il manque des lignes.

    Est-ce possible que je vous envoie un extrait de la table ?

    mercredi 14 juin 2017 15:19
  • Oui, c'est possible. Ce sera beaucoup plus facile avec un jeu de données !
    mercredi 14 juin 2017 18:39
  • Bonsoir,

    J'ai créé un extrait de ma base contenant la table et les 2 requêtes.

    La table est le résultat d'un pré sélection ce qui explique que pour la ;plupart des couples, il n'y a qu'une seule ligne (l'un a été sélectionné, pas l'autre).

    Quand vous exécutez la requête REmailSel, vous constatez qu'il manque BARDUT, BONTOUX, BRAUN .....

    Maintenant, comment fais-je pour vous envoyer cette base réduite ?

    merci d'avance

    mercredi 14 juin 2017 19:56
  • Bonsoir, 

    Vous pouvez me l'envoyer par e-mail : contact@custom-dev.fr

    mercredi 14 juin 2017 21:34
  • Bon, j'ai trouvé le soucis.

    Le petit cas que je n'avais pas prévu dans le cas où souhaite des champs supplémentaires, est le cas où une personne est en couple, mais que le conjoint n'est pas un adhérent. Si le nomprénom de la personne est inversée avec celui de son conjoint, alors la recherche par clé ne fonctionne plus (ce qui est tout à fait logique).

    Le plus simple reste donc de modifier la requête de recherche de doublon, afin de n'inverser le "nomprénom" et "conjoint" qu'en cas de nécessité, et pas pour tous les enregistrements.

    SELECT 
       IIf(NomPrénom<=conjoint Or conjoint Is Null,NomPrénom,conjoint) AS Nom1,
       IIf(NomPrénom<=conjoint Or conjoint Is Null,conjoint,NomPrénom) AS Nom2
    FROM Tmpadher AS T
    WHERE EXISTS(SELECT * FROM Tmpadher WHERE NomPrénom = T.conjoint)
    
    UNION
    
    SELECT NomPrénom, conjoint FROM Tmpadher AS T
    WHERE NOT EXISTS(SELECT * FROM Tmpadher WHERE NomPrénom = T.conjoint)
    

    Dans le premier select, on trait le cas où la personne et son conjoint est adhérent. Dans le second, le "reste du monde".

    jeudi 15 juin 2017 10:10
  • Alors là, c'est super !

    Le résultat est tout à fait correct et correspond bien à ce que je voulais.

    Je ne saisis pas entièrement la logique de la requête ..... mais c'est parfait.

    Merci pour ce précieux conseil et pour votre patience.

    bonne journée.


    • Modifié ibowl77 jeudi 15 juin 2017 13:12
    jeudi 15 juin 2017 13:08
  • Bonjour,

    Euh, avez-vous ajouté quelque chose dans cette réponse car c'est ce que j'ai mis en place et ça fonctionne très bien ?

    cordialement

    mardi 4 juillet 2017 08:44
  • Non, je n'ai rien ajouté. J'ai juste cliqué sur "Proposer comme réponse" dans la mesure où c'est ce dernier post qui vous a été utile ;)
    mardi 4 juillet 2017 08:51