Simplifier une requête MySQL

WRInaute discret
Bonjour à tous,

Voici ma requête
Code:
SELECT * 
            FROM Files F
            WHERE
                F.dom_id='$domid' &&
                (
                    (
                        EXISTS (SELECT T.tag_name,T.file_id FROM Tags T WHERE T.tag_name LIKE '%$keywords%')
                        &&
                        NOT EXISTS (SELECT T.file_id FROM Tags T WHERE T.file_id=(SELECT T.file_id AS TID FROM Tags T WHERE T.tag_name LIKE '%$keywords%'))
                    )
                    ||
                        EXISTS (SELECT T.tag_name,T.file_id FROM Tags T WHERE T.file_id=F.file_id && T.tag_name LIKE '%$keywords%')
                    ||
                        (F.file_name LIKE '%$keywords%' || F.file_description LIKE '%$keywords%')
                )


J'ai donc deux tables : Files et Tags
Un fichier n'a pas forcément de tag.

Du coups, lorsqu'on fais une requête plus simple du genre on n'a pas les fichiers qui n'ont pas de tags. Exemple :
Code:
    SELECT * FROM Files F, Tags T 
    WHERE F.dom_id='$domid'
          && (
            (F.file_name lIKE '%$keywords%' || F.file_description lIKE '%$keywords%')
            ||
            (T.tag_name lIKE '%$keywords%' && F.file_id=T.file_id)
          )
Du à la liaison entre Tags et Files avec file_id, on se prive des fichiers sans tags.


Donc, ma question ?
Est-ce que vous avez une idée de comment simplifier ma 1er requête ?
Voir même une autre façon de voir les choses ?

Merci d'avance,
Sky
 
WRInaute discret
ca devrait t'aider et bien simplifier les choses :)

SELECT
*
FROM Files F
LEFT OUTER JOIN Tags T USING (file_id)
ON T.tag_name LIKE '%$keywords%'
WHERE
F.dom_id='$domid'
 
WRInaute accro
Pas très clair, et je ne suis même pas sûr que ta requête complète fasse vraiment ce que tu veux.

Pour être sûr de bien comprendre, tu veux les lignes de Files:
- qui "matchent" sur file_name ou file_description;
- ou pour lesquelles il existe un tag qui correspond au mot-clef;
- ou pour lesquelles... ben là c'est pas clair... il n'existe pas de tag? pas de tag qui correspond au mot-clef?

Tu noteras que ton NOT EXISTS est toujours faux s'il existe un seul tag pour le mot-clef, et devrait donner une erreur dans les autres cas (parce que le sub-sub-select renverra 0 lignes ou plus de 1), et que ton EXISTS est vrai s'il existe un tag, donc la combinaison des deux est toujours fausse.

Au passage, en SQL "standard" c'est AND et OR, pas && et ||.

En supposant que tu veux les Files qui n'ont pas de tag associé, je pense que ça devrait marcher:
Code:
SELECT * FROM Files F LEFT JOIN Tags T ON (F.file_id = T.file_id) WHERE T.tag_name IS NULL OR T.tag_name LIKE '%$keywords%'
(je ne t'ai pas mis les autres conditions triviales)

Attention, s'il y a plusieurs tags qui correspondent tu peux avoir plusieurs fois la même ligne de Files. Un petit group by ou distinct pourrait donc s'avérer utile.

Sinon sans join, ce serait plutôt NOT EXISTS (SELECT 1 FROM Tags T WHERE t.file_id=F.file_id), non?

Jacques.
 
WRInaute discret
Bonjour

Merci à tous les deux.

Je revient vers vous dès que j'ai pu mettre vos exemples et conseils en pratique.

La requête actuel semble fonctionner, mais effectivement, pas tjrs évident d'être sur.

J'enrage de ne pas pouvoir tester de suite :)

Sky
 
WRInaute discret
Commence par tester la requête de jcaron... j'ai été trop vite en besogne et la mienne sortira en erreur.

il manque juste dedans le test sur le domaine ce qui donne :
SELECT *
FROM Files F
LEFT OUTER JOIN Tags T ON (F.file_id = T.file_id)
WHERE (T.tag_name IS NULL OR T.tag_name LIKE '%$keywords%')
AND F.dom_id='$domid'
 
WRInaute discret
Bonjour Ayor

Je n'avais pas compris que l'on pouvez utiliser IS NULL de cette façon.
Excellent, c'est nikel.

Merci beaucoup !

Sky
 
Discussions similaires
Haut