Question

Divers incarnations de cette question ont été posées ici, mais je pensais que je lui donnerais une autre photo.

J'ai eu une mise en page terrible base de données. Une entité unique (widget) a été divisé en deux tables:

CREATE TABLE widgets (widget_id int(10) NOT NULL auto_increment)

CREATE TABLE widget_data ( widget_id int(10), field ENUM('name','size','color','brand'), data TEXT)

était moins cet idéal. si on le souhaite trouver des widgets d'un nom spécifique, la couleur et la marque, je devais faire une triple jointure sur la table widget_data. donc je me suis converti au type de table raisonnable:

CREATE TABLE widgets (widget_id int(10) NOT NULL auto_increment, name VARCHAR(32),size INT(3),color VARCHAR(16), brand VARCHAR(32))

Cela rend la plupart des requêtes beaucoup mieux. Mais il rend la recherche plus difficile. Il fut un temps que si je voulais rechercher des widgets pour, disons, « %% de noir », je voudrais juste SELECT * FROM widget_data WHERE data LIKE '%black%'. Cela me donnerait toutes les instances de widgets qui sont de couleur noire, ou sont fabriqués par les industries, blackwell ou autre chose. Je ne sais même exactement quel champ adapté, et pourrait montrer que mon utilisateur.

comment puis-je effectuer une recherche similaire en utilisant la nouvelle disposition de la table? Je pourrais bien sûr faire WHERE name LIKE '%black%' OR size LIKE '%black%'... mais cela semble maladroit, et je ne sais pas encore quels champs adapté. Je pourrais exécuter une requête séparée pour chaque colonne que je veux apparie, ce qui me donnerait tous les matches et comment ils correspondent, mais ce serait un coup de performance. des idées?

Était-ce utile?

La solution

Vous avez deux exigences contradictoires. Vous voulez rechercher comme si toutes vos données sont dans un seul champ, mais vous voulez aussi identifier quel domaine spécifique a été adapté.

Il n'y a rien de mal à votre expression WHERE name LIKE '%black%' OR size LIKE '%black%'.... Il est une recherche parfaitement valable sur la table que vous avez défini. Pourquoi ne pas simplement vérifier les résultats dans le code pour voir lequel correspondait? Il est un minimum de frais généraux.

Si vous voulez une syntaxe plus propre pour votre SQL, vous pouvez créer une vue sur la table, en ajoutant un champ supplémentaire qui consiste à concaténer les autres champs:

CREATE VIEW extra_widget_data AS
  SELECT (name, size, color, brand,
          CONCAT(name, size, color, brand) as all_fields)
  FROM widget_data;

Ensuite, vous auriez à ajouter un index sur ce champ, ce qui nécessite plus d'espace, le temps processeur pour maintenir etc. Je ne pense pas que ça vaut le coup.

Autres conseils

Vous pouvez inclure une partie de l'expression WHERE en colonnes sélectionnant. Par exemple:

SELECT 
  *, 
  (name LIKE '%black%') AS name_matched,
  (size LIKE '%black%') AS size_matched
FROM widget_data 
WHERE name LIKE '%black%' OR size LIKE '%black%'...

Ensuite, vérifiez la valeur de name_matched sur le côté du script.

Je ne sais pas comment il aura une incidence sur la performance. Feal libre de le tester avant d'aller à la production

Vous voulez probablement regarder dans la capacité de recherche en texte intégral MySQL, ce qui vous permet de faire correspondre contre plusieurs colonnes de type varchar.

http://dev.mysql.com/doc /refman/5.1/en/fulltext-search.html

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top