MySQL, JOIN + WHERE ... AND ...

Résolu/Fermé
Rusk Messages postés 10 Date d'inscription mardi 4 mars 2008 Statut Membre Dernière intervention 31 mai 2010 - Modifié par Rusk le 31/05/2010 à 00:57
Rusk Messages postés 10 Date d'inscription mardi 4 mars 2008 Statut Membre Dernière intervention 31 mai 2010 - 31 mai 2010 à 14:38
Bonjour,
J'ai pas une experience tres longue de SQL et je voulais avoir votre avis sur une requête SQL.

J'ai 3 table comme ca:
global:    
id | name    

keyword_join:    
id | id_keyword | id_global    

keyword:    
id | keyword    


Je veux que SQL me retourne tout les noms de fichier qui correspond aux mots clé 'noel' OU 'neige', alors j'ai fait ca:
SELECT DISTINCT g.name   
    FROM global AS g    
        INNER JOIN keywords_join AS kj    
            ON g.id = kj.id_global    
        INNER JOIN keywords AS k    
            ON k.id = kj.id_keyword    

    WHERE k.keyword = 'neige' OR k.keyword = 'noel'    

et ca marche parfaitement.

Mais j'ai aussi besoin que il me retourne les fichiers qui contienne les mots clé
'noel' ET 'neige', alors j'ai esseiller de changer le OR par AND comme ca:
SELECT g.name  
    FROM global AS g    
        INNER JOIN keywords_join AS kj    
            ON g.id = kj.id_global    
        INNER JOIN keywords AS k    
            ON k.id = kj.id_keyword    

    WHERE k.keyword = 'neige' AND k.keyword = 'noel'    


Mais évidement il ne me retourne rien : /
edit:
car avec le OR il me resort une list du genre
          Name          | keyword 
------------------------------ 
noel-a-la-plage.jpg     | noel 
noel-sous-la-neige.jpg  | noel 
noel-sous-la-neige.jpg  | neige 
blanche-neige.jpg       | neige

Et aucune entrer ne peux avoir noel ET neige en même temps.
editend.
Alors je me suis creuser la soupière et je suis arriver a ceci:
SELECT COUNT(g.id) as num, g.name  
    FROM fexplorer_global AS g    
        INNER JOIN keywords_join AS kj    
            ON g.id = kj.id_global    
        INNER JOIN fexplorer_keywords AS k    
            ON k.id = kj.id_keyword    

    WHERE k.keyword = 'neige' OR k.keyword = 'noel'    
    GROUP BY g.id    
    HAVING num = 2    


Mais je trouvais ca un peux... barbare comme methode...

Donc ma question est la suivente: Y'a t'il une maniere plus clean d'arriver au meme resultat ?
sans le "COUNT(g.id) as num" et "GROUP BY k.keyword HAVING num = 2"

Merci déjà de m'avoir lu ^^
Et merci d'avance pour les réponses.

2 réponses

Désolé, javais pas pigé la problématique.

Ton problème est qu'une ligne de keyword_join ne peut te mener qu'à un seul mot clef, alors que tu en voudrais plusieurs

le subterfuge consiste à utiliser deux fois la table keyword_join ! une première fois pour sélectionner neige et une seconde pour sélectionner noel

ça donnerait (avec ma vieille syntaxe)
select distinct g.name
from global g
, keyword_join j1
, keywords k1
, keyword_join j2
, keywords k2
where g.id = j1.id_global
and j1.id_keyword = k1.id
and k1.keyword = 'neige'
and g.id = j2.id_global
and j2.id_keyword = k2.id
and k2.keyword = 'noel'
;
1
Rusk Messages postés 10 Date d'inscription mardi 4 mars 2008 Statut Membre Dernière intervention 31 mai 2010 1
31 mai 2010 à 14:38
Ah oui comme ca... pas con,
Par contre ca multiplie les lignes ci j'ai 20 mots clé...
Je me demande presque ci me méthode barbare est pas plus simple ^^

En tout cas merci
0
Salut,

Je suis pas très doué en MySQL ni en JOINs qu'ils soient INNER ou OUTER... Je vais donc me contenter d'une syntaxe un peu vieillotte mais qui devrait fonctionner

A. La liste des keywords neige ou noel :
select id
from keywords
where keyword in ('neige', 'noel')

B. La liste des joints associés à neige ou noel
nb: comme l'id de keyword_join ne sert à rien, je me contente de ressortir les id_global
select j.id_global
from keyword_join j, keywords k
where j.id_keyword = k.id
and k.keyword in ('neige', 'noel')

C. La liste des noms associés à neige ou noel (avec DISTINCT pour éviter les répétitions)
select distinct g.name
from global g, keyword_join j, keywords k
where g.id = j.id_global
and j.id_keyword = k.id
and k.keyword in ('neige', 'noel')

Voilà ! J'espère que ça fonctionne chez toi et que ça te filera le coup de pouce demandé.
-1
Rusk Messages postés 10 Date d'inscription mardi 4 mars 2008 Statut Membre Dernière intervention 31 mai 2010 1
Modifié par Rusk le 31/05/2010 à 00:32
Merci je connaissais pas l'opérateur IN ^^
Mais par contre ca semble pas résoudre mon "problème", car je veux les nom avec noel ET neige. Alors que l'opérateur IN est équivalent a OR
En faite ci je fait (sans DISTINCT):
SELECT g.name  
    FROM global AS g   
        INNER JOIN keywords_join AS kj   
            ON g.id = kj.id_global   
        INNER JOIN keywords AS k   
            ON k.id = kj.id_keyword   

    WHERE k.keyword = 'neige' OR k.keyword = 'noel'   

Il me resort une liste du genre:
          Name          | keyword 
------------------------------ 
noel-a-la-plage.jpg     | noel 
noel-sous-la-neige.jpg  | noel 
noel-sous-la-neige.jpg  | neige 
blanche-neige.jpg       | neige

Et je veux que il me ressorte que les nom de fichier qui ont noel ET neige,
Mais en changent le OR par AND il me trouve rien car aucune entrer ne peux avoir neage ET noel en même temps.
Donc j'ai utiliser un subterfuge mais je trouve pas ca propre du tout.
0