2010-02-10 5 views
0

Je suis en train d'apprendre la normalisation, alors s'il vous plaît pardonnez-moi si c'est une question stupide. J'ai une table TBL_Users avec la clé primaire étant ID. Pour savoir qui est amis avec qui ma dernière pensée était de faire une table avec deux clés étrangères, dont les deux sont l'identité de l'autre personne. Cependant, plus je pense à cela, je ne peux pas m'empêcher de penser qu'il doit y avoir un meilleur moyen. Ce modèle signifie soit que je dois dupliquer toutes les informations, soit appeler deux fois TBL_Friends.lier deux clés primaires différentes d'une table dans une deuxième table

IE si la table est

 
+----+--------+ 
| ID | Friend | 
+----+--------+ 
| 1 | 2  | 
| 2 | 1  | 
+----+--------+ 

J'ai des informations dupliquées et doivent faire deux appels pour ajouter/supprimer des amis.

D'autre part, si je fais juste

+----+-----+ 
| ID | ID2 | 
+----+-----+ 
| 1 | 2 | 
| 3 | 1 | 
| 4 | 1 | 
+----+-----+

La situation semble être encore pire parce que je dois interroger la base de données deux fois chaque fois que je veux faire quelque chose, que ce soit recueillir des informations ou ajouter/supprimer copains.

Sûrement il y a une solution plus simple que je suis en train de négliger?

+0

La dernière solution que vous mettez là semble bien. Pourquoi pensez-vous "avoir à interroger la base de données deux fois"? Vous deuxième table "amis" serait juste deux colonnes, dont les deux sont des clés étrangères. Si vous avez un enregistrement de [1,2], cela signifie que 1 est ami avec 2 et vice-versa. – catchdave

+0

Dites 1 est ami avec 2, 3 et 4. La table peut ressembler à: (voir la version éditée du dernier tableau ci-dessus). Pour savoir qui sont les amis de 1, n'aurais-je pas à faire deux requêtes, une sur l'ID et l'ID2? – aslum

+1

Utilisez simplement une requête avec une clause "OR". "SELECT (CAS LORSQUE id1 = 1 PUIS id2 ELSE id1 END) Comme ami_id WHERE id1 = 1 OU id2 = 1". Cela correspond au cas simple que vous avez fourni. Si la logique de votre entreprise est plus complexe, il peut être judicieux de dénormaliser cette table (c'est-à-dire: similaire à votre idée dupliquée) ou une autre conception. Si c'est le cas, alors peut-être esquisser plus de la conception autour des utilisateurs et des amis et je peux écrire une bonne réponse. – catchdave

Répondre

1

Vous n'avez pas besoin d'utiliser deux requêtes, utilisez simplement une requête avec une clause OR.

SELECT 
    (CASE WHEN 
     WHEN id1 = XXX THEN id2 
     ELSE id1 
    END) AS friend_id 
WHERE 
    id1 = XXX OR id2 = XXX 

XXX est l'ID de l'utilisateur que vous êtes à la recherche vers le haut. Cela correspond au cas simple que vous avez fourni.

Si votre modèle devient beaucoup plus complexe, nous pouvons regarder d'autres solutions de tables et/ou de dénormalisation comme votre première solution.

+0

Et je suis d'accord avec @APC avec sa réponse ci-dessous. Ma solution est basée sur l'hypothèse que [1,2] est équivalent à [2,1]. Cela peut ou peut ne pas être le cas. – catchdave

+0

Une union serait meilleure; De cette façon, vous pouvez indexer sur ID1 et index sur ID2 et la base de données peut exécuter les deux requêtes rapidement. Un OR rend plus difficile l'utilisation d'index. –

1

La question à laquelle vous devez répondre est la suivante: les deux énoncés suivants sont-ils équivalents?

  1. Bob est un ami d'Al
  2. Al est un ami de Bob

Cela dépend du contexte. Dans les sites de réseautage social, Al et Bob ne sont que des noeuds sur un graphique, et tant qu'il y a un lien entre eux, cela suffit. Mais si Al traque Bob alors Al pourrait affirmer la déclaration n ° 1 autant qu'il le souhaite, Bob ne sera jamais d'accord avec la déclaration n ° 2. Ou considérez comme un statemen analogue:

  1. Bob est le directeur d'Al
  2. Al est le gérant de Bob

Il est rare que ces deux déclarations peuvent être vraies en même temps, mais il y a des complexes de gestion structures là-bas.

Dans les deux cas, votre première table ne contient pas de données en double, car (1,2) n'est pas identique à (2,1). Si vous optez pour la seconde solution, vous devez appliquer une règle qui stipule que si (1,2) existe, (2,1) ne peut pas exister.

Il existe des situations dans lesquelles votre première solution est la bonne et d'autres dans lesquelles la seconde est la bonne. En d'autres termes, la modélisation des données est difficile :)

L'élément clé est, d'abord obtenir votre modèle logique correct. Oubliez le SQL jusqu'à ce qu'il écrit les requêtes. Si vos tables sont conçues correctement, le SQL circulera. Ou, pour le dire autrement, si vous avez du mal à écrire la requête, il y a des chances que votre modèle de données soit erroné.

+0

Je prévois de faire une étape "ajouter un ami" (qui sera une table différente, mais similaire). Cela devrait être plus simple car, à mesure que les demandes sont acceptées, les informations seront supprimées de la table des requêtes et ajoutées à la table des amis. Merci. – aslum