2009-07-15 5 views
3

Existe-t-il un bon moyen d'implémenter une relation plusieurs-à-plusieurs entre des lignes d'une même table?Table auto-référentielle plusieurs-à-plusieurs

Exemple: table pour stocker des synonymes de mots:

-- list of words 
CREATE TABLE word (
    id integer  PRIMARY KEY, 
    word varchar(32) NOT NULL UNIQUE 
); 
INSERT INTO words (id, word) VALUES (1, 'revolve'); 
INSERT INTO words (id, word) VALUES (2, 'rotate'); 

-- M:M link between words 
CREATE TABLE word_link (
    word1 integer  REFERENCES word(id) NOT NULL, 
    word2 integer  REFERENCES word(id) NOT NULL, 
    PRIMARY KEY (word1, word2) 
); 

résultats de solution évidente dans le tableau probablement pas-1NF, contenant des données en double:

INSERT INTO word_link(word1, word2) VALUES (1, 2); 
INSERT INTO word_link(word1, word2) VALUES (2, 1); 

Bien que la duplication peut être traitée en ajoutant (word1 < word2) check, cela rend les SELECTs beaucoup plus complexes (union par rapport à trivial join) et est assez arbitraire. Ce cas spécifique peut bénéficier d'une table auxiliaire (telle que 'signification', donc les mots sont M: N liés au sens commun et pas les uns aux autres, donnant un schéma plus propre), mais je suis intéressé par une solution générale.

Y a-t-il donc une meilleure façon (et on l'espère commune) de mettre en œuvre une telle relation M: M?

Répondre

1

Dans ce cas j'ajouterais une CHECK CONSTRAINT sur UPDATE et sur INSERT pour appliquer ce mot1 est toujours inférieur à word2 et vice-versa.

0

je créer une vue qui a été la suivante:

select distinct 
    case when word1 < word2 then word1 else word2 end as word1, 
    case when word1 < word2 then word2 else word1 end as word2 
from 
    word_link 

De cette façon, vous avez toujours un endroit propre, aucune liste en double qui est facile à sélectionner. J'ai trouvé que c'est à peu près aussi propre que vous pouvez avoir à faire une relation plusieurs-à-plusieurs.

+0

ummm ... votre déclaration de cas a les mêmes critères pour les deux cas. Je présume que vous vouliez dire word2

+1

@Nathan: Même condition, résultats différents. La première colonne utilise toujours le mot plus petit, tandis que la deuxième condition utilise toujours le plus grand. – Eric

+0

ah je comprends maintenant –