2010-07-23 8 views
3

Il ya quelque temps, j'ai posté une question différente concernant l'ordre des colonnes. Bien que cette question ne se rapporte pas à l'ordre des colonnes, on m'a suggéré de faire en sorte que ma table diffère de la façon dont je le faisais.n * n table vs (n^2) * 3 table dans mysql

Disons que je vends 100 produits. Certains de ces produits sont compatibles les uns avec les autres, d'autres non. Certains n'ont pas encore été testés (je n'ai pas mentionné cette partie dans ma dernière question).

Serais-je mieux faire une table mySQL comme:

NAME   PRODUCT1  PRODUCT2  PRODUCT3  PRODUCT4 .... 
product1  yes   no   maybe  yes 
product2  maybe  yes   no   no 
product3  maybe  yes   no   no 
product4  maybe  yes   no   no 
... 

ou de faire la table comme:

FIRST  SECOND  COMPATIBLE? 
Product1 Product1 Yes 
Product1 Product2 Yes 
Product1 Product3 No 
Product1 Product4 Maybe 
Product2 Product1 Maybe 
Product2 Product2 Maybe 
Product2 Product3 No 
Product2 Product4 Maybe 
Product3 Product1 Yes 
Product3 Product2 Yes 
Product3 Product3 No 
Product3 Product4 Yes 
Product4 Product1 Yes 
Product4 Product2 No 
Product4 Product3 No 
Product4 Product4 Maybe 

On m'a dit que la deuxième méthode serait mieux, mais je ne ai pas mentionner qu'il y avait aussi l'option «peut-être» (et pas purement oui/non), ce qui signifie que la troisième colonne devrait être ajoutée à la deuxième table. En tant que mySQL'er inexpérimenté, je demande, quelle table serait plus efficace, plus facile à entretenir, et que recommanderiez-vous?

Répondre

3

La deuxième option est encore meilleure (même avec la troisième colonne, ce qui ne pose aucun problème), car elle vous permet d'ajouter facilement de nouveaux types de produits sans modifier les tables. (Le terme technique pour cela est que le schéma est mieux "normalisé"). C'est beaucoup plus facile à maintenir. En outre, cela signifie que vous pouvez vous joindre à travers cette table beaucoup plus facilement, ou faire des requêtes pour répondre «quel est le produit le moins cher avec lequel le produit 1 est compatible», ce qui serait très difficile à faire avec la première table.

+0

J'espère que cela ne vous dérange pas une autre question. J'ai déjà la deuxième table prévue mais pas encore remplie. Ce que je veux dire par là, c'est que chaque produit est compatible avec lui-même, donc je l'ai rempli pour chaque produit qui est compatible avec lui-même. Je n'ai pas de compatibilités lors du mixage des produits. Existe-t-il un moyen de remplir rapidement chaque produit en SECOND pour chaque FIRST non unique? J'espère que vous comprenez ma mauvaise formulation – thomas

+0

@thomas: ce serait probablement mieux fait en écrivant du code qui insère en lisant la liste des produits existants de ... quelque chose? – FrustratedWithFormsDesigner

+0

@thomas, heureux je pourrais aider ... S'il vous plaît poser votre deuxième question comme une autre question sur StackOverflow, plutôt que dans les commentaires :) Vous pouvez poster le lien ici une fois que vous avez! – nicolaskruchten

2

Stick avec la deuxième option. Si vous ajoutez ou supprimez des produits, vous n'affectez que quelques lignes. Si vous utilisez la première option et ajoutez/supprimez des produits, vous modifiez la structure de la table.

-1

Il existe une troisième option - une forme "semi-normalisée". Dans ce cas, vous auriez une structure quelque chose comme ceci:

Product DefinitelyCompatible MaybeCompatible 
---------------------------------------------- 
1  '2, 3, 4'    '5' 
2  '1, 4'    '3' 
3  '1'     '3, 4' 
4  '1, 2'    '3' 
5  ''     '1' 

Lorsque le premier champ est l'ID du produit, et les deuxième et troisième champs sont des chaînes qui contiennent des listes d'ID. En utilisant cette structure, vous pouvez utiliser la fonction MySQL FIND_IN_SET() pour chercher dans les listes, ou si vous voulez rechercher les compatibilités d'un produit donné, vous n'avez besoin que d'aller chercher une ligne et de diviser les chaînes vous-même. Cela vous permet d'avoir autant de lignes que de produits (dans une table Nx3), tout en minimisant le nombre de lignes que vous devez modifier pour ajouter un nouveau produit (ou en mettre à jour un existant). Une note supplémentaire sur la performance - en supposant que les relations sont symétriques (si un -compat-> b, puis b -compat-> a), vous n'avez même pas besoin d'utiliser FIND_IN_SET() - vous pouvez simplement aller chercher quel que soit l'objet (a ou b) vous devez obtenir les listes pour (si vous avez besoin de tout ce qui est compatible avec 23, alors vous allez chercher la rangée 23, si vous voulez voir si 4 est compatible avec 5, vous pouvez aller chercher sa rangée et voir si autre apparaît dedans). FIND_IN_SET() serait alors seulement nécessaire si la vérification est une partie d'une sous-requête, plutôt que dans votre code.

+1

Ce n'est certainement pas la meilleure façon de réaliser cette association, surtout dans une base de données de produits comme celle-ci. Peut-être que dans les scénarios d'entrepôt de données, cette solution serait un travail, mais njk souligne ci-dessous mais l'un des nombreux problèmes avec cette conception. – WCWedin

+0

Cela peut fonctionner, mais je serais inquiet que les 'DefinitelyCompatible' et' MaybeCompatible' ne soient pas bien indexés. Que cela compte ou non dépend des requêtes. En outre, je ne suis pas sûr de savoir comment cela est portable pour les autres plates-formes qui n'ont pas de fonction 'FIND_IN_SET()'. – FrustratedWithFormsDesigner

+1

En fait, maintenant que j'y pense, il ne sera peut-être jamais nécessaire d'indexer 'DefinitelyCompatible' et' MaybeCompatible'. Rejoindre des requêtes peut être difficile cependant. – FrustratedWithFormsDesigner