IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PostgreSQL Discussion :

Gestion des doublons sur une clef inversée


Sujet :

PostgreSQL

  1. #1
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut Gestion des doublons sur une clef inversée
    Bonsoir à tous

    J'ai été confronté ce matin à un petit soucis d'organisation et je n'ai pas su décider laquelle était la meilleure

    Je dois gérer une relation de voisinage entre deux items. J'ai donc créé la table principale
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    create table item (
        id_item integer not null,
        ..., ..., ...
    );
     
    alter table item add constraint pkey_item primary_key (id_item);
    Jusque là, pas de souci.

    Puis, ma table voisinage
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    create table voisin (
        id_item1 integer not null,
        id_item2 integer not null
    );
    alter table voisin add constraint pkey_item primary_key (id_item1, id_item2);
    Puis les foreign keys. Jusque là, ça va encore.

    Mais mon problème c'est quand je veux insérer un voisin style item 1 voisin avec item 5. Là, j'ai 2 choix possibles
    1) soit je rentre systématiquement dans ma table le tuple (1, 5) puis le tuple (5, 1)

    2) soit je ne rentre que le tuple (1, 5) en disant "si 1 est voisin avec 5, alors 5 est automatiquement voisin avec 1".
    Mais dans ce cas, j'aimerais bloquer l'insertion du tuple (5, 1) si le tuple (1, 5) est déjà dans la table. Et là, j'ai pas trouvé comment faire
    J'ai essayé de créer une contrainte d'unicité sur le groupe (id_item2, id_item1) mais ça n'a rien empêché du tout.

    Et donc ma question c'est: vaut-il mieux choisir la solution 1 et avoir chaque relation de voisinage écrite 2 fois ou vaut-il mieux utiliser la solution 2 mais sans pouvoir empêcher une insertion existant déjà dans le sens inverse ? Et corollaire: y a-t-il moyen, dans Postgres, d'empêcher cette insertion si le tuple inverse est déjà présent dans la table ?

    Merci à tous
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  2. #2
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Points : 2 579
    Points
    2 579
    Par défaut
    Les deux solutions sont possibles.

    Ma préférence va à la 1ère car elle modélise la réalité. A savoir que votre lien est bidirectionnel donc les deux sens doivent être stockés.

    La deuxième solution fonctionne aussi. Mais elle obligera a requêter dans les deux sens.

    Pour les éléments techniques d'implémentation, vous pouvez utiliser les triggers et les vues. La première solution peut utiliser un trigger after insert qui insère le 2ème tuple dans le sens inverse du premier. La deuxième solution peut utiliser un trigger before insert qui vérifie si le tupe inverse n'est pas déjà présent et une vue qui reconstruit les deux sens :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    CREATE VIEW ... AS 
    SELECT ID_ITEM1 as ID_ITEM1 , ID_ITEM2 as ID_ITEM2
    FROM VOISIN
    UNION ALL
    SELECT ID_ITEM2, ID_ITEM1
    FROM VOISIN

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par vmolines Voir le message
    Les deux solutions sont possibles.

    Ma préférence va à la 1ère car elle modélise la réalité. A savoir que votre lien est bidirectionnel donc les deux sens doivent être stockés.
    Salut

    C'est aussi ce que je pense. Parce que, plus tard, quand il faudra chercher les voisins de X faudra chercher "select item2 where item1=X union select item1 where item2=X". Et là, ça risque de devenir bien ch...

    Citation Envoyé par vmolines Voir le message
    Pour les éléments techniques d'implémentation, vous pouvez utiliser les triggers et les vues. La première solution peut utiliser un trigger after insert qui insère le 2ème tuple dans le sens inverse du premier. La deuxième solution peut utiliser un trigger before insert qui vérifie si le tupe inverse n'est pas déjà présent et une vue qui reconstruit les deux sens :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    CREATE VIEW ... AS 
    SELECT ID_ITEM1 as ID_ITEM1 , ID_ITEM2 as ID_ITEM2
    FROM VOISIN
    UNION ALL
    SELECT ID_ITEM2, ID_ITEM1
    FROM VOISIN
    Je connaissais les trigger mais j'y suis pas encore habitué. J'avais bien pensé qu'un trigger me permettrait de checker l'inversion mais j'avais pas pensé aussi au trigger qui insère automatiquement le tuple inversé.

    Toutefois, aujourd'hui j'ai trouvé une solution simple qui permet de garantir l'unicité sans se préoccuper du sens du tuple.
    Il suffit de créer un index unique sur ((id_item1 + id_item2), (id_item1 * id_item2))
    Etant donné que l'addition et multiplication sont commutatives, le produit et la somme seront égaux quel que soit le sens du tuple. Et deux tuples différents donneront alors un couple (somme, produit) différent.
    C'est en pensant à l'algo de Diffie et Hellman, qui avaient aussi une problématique analogue, que j'ai eu cette idée...

    Ceci dit, j'aime bien l'idée du trigger qui insère automatiquement le tuple inverse. Merci beaucoup
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Gestion des erreurs sur une sauvegarde
    Par Zak Blayde dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 22/05/2008, 00h22
  2. identifier des doublons sur une clé composé
    Par laurentci dans le forum Langage SQL
    Réponses: 2
    Dernier message: 11/01/2008, 12h09
  3. Gestion des Callbacks sur une scrolling Bar
    Par neptune2024 dans le forum Interfaces Graphiques
    Réponses: 1
    Dernier message: 22/11/2007, 09h31
  4. Gestion des erreurs sur une commande multiple
    Par domiq44 dans le forum Shell et commandes GNU
    Réponses: 5
    Dernier message: 05/10/2006, 15h03
  5. récupérer des données sur une clef USB
    Par mullger dans le forum Périphériques
    Réponses: 6
    Dernier message: 25/09/2006, 18h38

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo