Page 1 sur 1

Opérateur LIKE sur plusieurs tables: mission impossible?

Posté : 01 févr. 2007, 14:36
par Victor BRITO
Salut à tous!

Pour un site pro en cours de refonte, je mets au point un formulaire de recherche qui consiste à chercher un ou plusieurs mots dans la base de données. Jusqu'ici, rien à signaler.

La base de données comporte plusieurs tables, dont une listant les différents menus, une autre les rubriques contenues dans les menus et une troisième les fiches contenues dans les rubriques. Des clés primaires et des clés d'index sont présentes pour le jonglage entre tables. Et ce, pour avoir un fil d'ariane du genre Prêt-à-porter (menus) > Lingerie (rubriques) > Nom d'une enseigne (fiches).

Dans la base de données, on enregistre une rubrique "Lingerie féminine", une rubrique "Lingerie masculine" (rubriques attachées au menu "Prêt-à-porter") et cinq fiches, dont quatre sont attachées à la rubrique "Lingerie féminine" (parmi ces quatre, une a un nom comportant le mot "lingerie") et une à la rubrique "Lingerie masculine".

On obtient donc les données suivantes:

Code : Tout sélectionner

Table rubriques +----+---------+--------------------+--------------------+ | id | id_menu | nom | url | +----+---------+--------------------+--------------------+ | 1 | 15 | Lingerie masculine | lingerie-masculine | | 2 | 15 | Lingerie féminine | lingerie-feminine | +----+---------+--------------------+--------------------+ Table fiches +----+-------------+---------------------+-------------------+-------------------+ | id | id_rubrique | description_resume | nom | url | +----+-------------+---------------------+-------------------+-------------------+ | 82 | 1 | Description rapide. | Majoss | majoss | | 85 | 2 | Description rapide. | Julie A Lingerie | julie-a-lingerie | | 86 | 2 | Description rapide. | Lolie Belle | lolie-belle | | 87 | 2 | Description rapide. | Des Voiles et Moi | des-voiles-et-moi | | 88 | 2 | Description rapide. | Collants.fr | collants.fr | +----+-------------+---------------------+-------------------+-------------------+
On cherche le mot "lingerie".

Lorsqu'on effectue la requête suivante:

Code : Tout sélectionner

SELECT fiches.description_resume AS description_resume, fiches.nom AS fiches_nom, fiches.url AS fiches_url, rubriques.nom AS rubriques_nom, rubriques.url AS rubriques_url, menus.nom AS menus_nom, menus.url AS menus_url FROM fiches, rubriques, menus WHERE id_rubrique=rubriques.id AND id_menu=menus.id AND fiches.nom LIKE '%Lingerie%'
un seul résultat est retourné (logique).

Même logique (5 résultats retournés) avec cette requête-ci:

Code : Tout sélectionner

SELECT fiches.description_resume AS description_resume, fiches.nom AS fiches_nom, fiches.url AS fiches_url, rubriques.nom AS rubriques_nom, rubriques.url AS rubriques_url, menus.nom AS menus_nom, menus.url AS menus_url FROM fiches, rubriques, menus WHERE id_rubrique=rubriques.id AND id_menu=menus.id AND rubriques.nom LIKE '%Lingerie%'
En revanche, si l'on effectue cette requête:

Code : Tout sélectionner

SELECT fiches.description_resume AS description_resume, fiches.nom AS fiches_nom, fiches.url AS fiches_url, rubriques.nom AS rubriques_nom, rubriques.url AS rubriques_url, menus.nom AS menus_nom, menus.url AS menus_url FROM fiches, rubriques, menus WHERE id_rubrique=rubriques.id AND id_menu=menus.id AND fiches.nom OR rubriques.nom LIKE '%Lingerie%'
un nombre astronomique de résultats est retourné.

Et si on ajoute des parenthèses comme suit:

Code : Tout sélectionner

AND (fiches.nom OR rubriques.nom) LIKE '%Lingerie%'
aucun résultat n'est retourné (alors qu'on s'attend au contraire).

Serait-il impossible d'appliquer la commande de contrôle LIKE à plusieurs colonnes réparties sur plusieurs tables à la fois? :oops:

Posté : 01 févr. 2007, 17:55
par Ryle
Le problème ne vient pas tant de la commande like, mais de la jointure que tu fais entre les tables. Comme il n'y a aucune condition de jointure, chaque résultat trouvé dans ta première table est multiplié par le nombre de résultat trouvé dans la seconde pour t'offrir une liste de couple exaustive :)

Il va donc falloir réaliser une requête par table, mais en revanche, tu peux grace à la commande sql UNION n'en exécuter qu'une seule :

Code : Tout sélectionner

SELECT fiches.nom AS nom, ... , 'fiches' AS quelle_table FROM fiches WHERE nom LIKE '%Lingerie%' UNION ALL SELECT rubriques.libelle AS nom, ... , 'rubriques' AS quelle_table FROM rubriques WHERE nom LIKE '%Lingerie%' UNION ALL ...
Chaque requette retourne les même nombre et type de champs et le union fait qu'ils sont regroupés comme s'il s'agissait d'une seule table interrogée. Le 'quelle_table' permet si nécessaire de savoir dans quelle table a été trouvé le résultat :)

Posté : 01 févr. 2007, 21:30
par Ajoloca
Bonsoir,

Je ne sais pas si la requête fera ce que tu veux, mais tu as une erreur.

Quand tu tu utilises les opérateurs logiques tu dois donner une valeur de chaque coté de l'opérateur.

Il ne peut deviner ce que tu cherches. Si tu veux faire (si a et b sont égales à c)
tu devras l'écrire si a égal à c ET b égal à c, car si tu écris si a ET b égal c il ne peut interpréter à quoi tu veux comparer a.
AND (fiches.nom LIKE '%Lingerie%' 
 OR rubriques.nom LIKE '%Lingerie%')