Vous semblez être intéressé par :
-- a and b are related by the association of interest
Foo(a, b)
-- foo(a, b) but not foo(a2, b) for some a2 <> a
Boring(a, b)
unique(b)
FK (a, b) references Foo
-- foo(a, b) and foo(a2, b) for some a2 <> a
Rare(a, b)
FK (a, b) references foo
Si vous voulez des requêtes pour être libre, il suffit de définir Foo. Vous pouvez l'interroger pour Rare.
Rare = select * from Foo f join Foo f2
where f.a <> f2.a and f.b = f2.b
Toute autre conception souffre de la complexité de la mise à jour pour maintenir la cohérence de la base de données.
Vous avez une inquiétude floue sur le fait que Rare soit beaucoup plus petit que Foo. Mais quelle est votre exigence n'est-ce que n sur un million d'enregistrements Foo étant nombreux :nombreux par lesquels vous choisiriez un autre design ?
Le prochain niveau de complexité est d'avoir Foo et Rare. Les mises à jour doivent respecter l'équation ci-dessus.
Il semble extrêmement peu probable qu'il y ait un avantage à réduire la redondance de 2 ou 3 sur un million de Foo + Rare en n'ayant que Boring + Rare et en reconstruisant Foo à partir d'eux. Mais il peut être avantageux de définir un indice unique (b) pour Boring qui maintiendra qu'un b n'a qu'un seul a. Quand vous avez besoin de Foo :
Foo = select * from Boring union select * from Rare
Mais vos mises à jour doivent maintenir cela
not exists (select * from Boring b join Rare r where b.b = r.b)