2010-12-09 18 views
2

Je crée un système pour stocker des données de stat utilisateur comme suit:MySQL Rechercher

 
Table Stats 
=========== 
id name 
----------- 
1  height 
2  weight 
3  eye_colour 
4  etc... 
 
Table Stat_Options 
================== 
id stat_id name 
1  1   170cm 
2  1   172cm 
3  1   174cm 
4  2   60kg 
5  2   65kg 

Et je stocke les IDs des stat_options dans le tableau utilisateur comme suit:

 
Table User_Stats 
================ 
id user_id height weight eye_colour etc... 
--------------------------------------------------------- 
1  10   3   5   7 

Le raisonnement derrière le stockage de l'ID était que le 'nom' de l'option stat_option peut toujours être changé et que l'enregistrement de l'utilisateur n'aurait pas besoin d'être changé.

Mais en regardant cela, je pense qu'il peut présenter un problème, surtout lors de la recherche. Par exemple si je veux rechercher tous les utilisateurs entre deux hauteurs spécifiques? Une solution qui vient à l'esprit est d'insérer un champ 'value' dans la table Stat_Options, mais je ne sais toujours pas si cela fonctionnerait. Aucune suggestion?

+0

'SELECT ... FROM STAT_OPTIONS O stat stat_id = 1 ET nom ENTRE x ET y' - qu'est-ce qui est difficile à ce sujet? Joignez-vous à la table STATS si vous avez besoin de stat_id basé sur la valeur du nom ... –

Répondre

1

Le problème avec ce type de conception est que vous mixez des valeurs quantitatives (hauteur, poids) avec des valeurs qualitatives (eye_colour) dans votre tableau Stat_Options. Si vous voulez absolument cela, divisez les valeurs quantitatives et qualitatives en 2 colonnes.

Table Stat_Options 
================================== 
id stat_id name value unit 
=== ======= ===== ===== ===== 
    1  1 170cm 170  cm 
    2  1 172cm 172  cm 
    3  1 174cm 174  cm 
    4  2 60kg  60  kg 
    5  2 65kg  65  kg 
    6  3 black NULL black 

Alors que d'autres ont suggéré, JOIN tables pour obtenir des valeurs BETWEEN x AND y.

+0

Serait-il une bonne idée de stocker le valeurs qualitatives sous forme d'entiers (dans la colonne de valeur)? Par exemple noir = 1, marron = 2, et ainsi de suite ...? – GSTAR

+1

@GSTAR: Vous pouvez le faire ... Ou vous pouvez même laisser 'value' et' unit' à 'NULL', car vous ne les utiliserez pas vraiment de toute façon. – Danosaure

0

De votre exemple, pourriez-vous obtenir tous les utilisateurs avec une hauteur entre x et y en questionnant:

Select user_id from User_Stats where User_Status.height between x and y 
+0

Sauf qu'il semble stocker la hauteur avec les unités incluses. Je suis d'accord, la table doit être divisée, à tout le moins, avec une valeur et peut-être un champ d'unités. De là, une jointure pour le filtrage est triviale. –

1

à mon humble avis, vous devez utiliser une table de recherche comme votre Stat_Options uniquement pour les cas où l'attribut a un fini nombre de valeurs, comme la couleur des yeux. Essayer d'utiliser une table comme celle-ci pour des attributs qui (théoriquement) ont un nombre infini de valeurs, comme la taille et le poids, causera, comme vous l'avez déjà deviné, des maux de tête importants. Je stockerais ces valeurs directement dans votre table User_Stats à la place.

+0

Idéalement, je veux éviter de stocker des valeurs directement dans ma table utilisateur, je préfère simplement référencer un identifiant et récupérer le nom de cette sélection dans la table liée. De cette façon, je peux toujours mettre à jour le nom de la sélection sans avoir à mettre à jour tous les enregistrements utilisateur avec le nouveau nom. – GSTAR

+0

OK, mais dans votre exemple de hauteur, voudriez-vous jamais modifier le nom dans 'Stat_Options' de 170cm à 190cm. Vous changeriez soudainement la taille de chaque utilisateur à qui l'ID a été attribué, ce que vous ne souhaitiez manifestement pas. –

+0

C'est vrai, mais ce qui m'a le plus préoccupé, c'est si je décide d'échanger entre les unités. Selon les commentaires du site, je peux décider de stocker la hauteur en pouces plutôt qu'en CM. Donc, je voulais avoir la flexibilité que je pouvais échanger entre les unités sans affecter les données de l'utilisateur .. – GSTAR

0
SELECT user_id FROM User_Stats WHERE height BETWEEN 170 AND 172; 

Je devinerais celui-là.

Mais pour la structure de vos tables je peux suggérer les éléments suivants:

  1. Il n'y a pas besoin de la table Statistiques car il peut être inclus sans problème à l'intérieur du tableau de User_Stats. De cette façon, vous normaliseriez mieux l'utilisation des tables. SI et seulement SI les valeurs de hauteur et de poids peuvent être plus que les 3 que vous avez là (par exemple 180, 183, 192, 200, 110 ...) alors je suggère la même chose que le point 1. Pour drop the table et inclus dans la table User_Stats car cette valeur peut changer et n'est pas vraiment nécessaire pour créer une nouvelle table juste pour ça. De cette façon, vous pouvez effectuer des recherches plus rapidement et facilement en comparant tout ce que vous voulez dans une seule table.

+0

Non parce que la hauteur est une clé étrangère .. Jamais un entier dans ce cas .. – bAN

+0

Selon mon exemple de code, ce n'est pas juste un valeur entière (il stocke l'unité avec). – GSTAR

+0

Je vois. Donc vous voulez dire dans un format hiérarchique. J'ai entendu des arguments pour et contre ce format, à la fin j'ai décidé de garder tout dans des tables séparées. Je ne pense pas que tout mettre dans une table est la solution à ce problème spécifique. – GSTAR

0

Ce n'est pas une bonne idée de faire comme ça .. Utilisez Stat_option pour lier dropdownlist pour exemple, si vous avez un certain nombre ne pas changer souvent de valeurs ..

pourquoi ne pas suffit d'ajouter un champ entier à la table User-stats avec la hauteur?

Mais si vous voulez vraiment que vous pouvez faire:

SELECT * FROM USER_STATS 
INNER JOIN STAT_OPTION 
ON USER_STATS.height in (
SELECT ID FROM Stat_Options 
WHERE NAME BETWEEN 170 AND 175) 

Ou quelque chose comme ça, je ne suis pas d'habitude avec MySql ..

+0

Je vois. Donc, vous voulez dire avoir un champ 'value' avec le nom, par exemple, name = "170cm", value = "170"? – GSTAR

+0

Pourquoi ne pas mettre la valeur 170 dans le champ 'height' dans le datatable 'USER_STATS'? Ce sera plus facile .. Pas un lien pour faire des tables juste pour le plaisir :-) – bAN

+0

Hmm je suppose que c'est ce que je finirai par faire! – GSTAR