2016-01-01 5 views
0

Je travaille actuellement sur un système pour permettre des documents à être étiquetés avec des mots clés et une table de la forme:Table unique INTERSECT alternatif

CREATE TABLE `KeywordsToDocuments` (
    `keywordID` int NOT NULL, 
    `documentID` int NOT NULL); 

Il est possible pour chaque document à associer à de nombreux mots-clés, et pour chaque mot-clé à associer à de nombreux documents. Malheureusement une simple instruction AND n'atteint pas ce dont j'ai besoin car aucune ligne ne satisfera plusieurs valeurs de KeywordID, à la place une publication est associée à plusieurs mots-clés en incluant son ID sur plusieurs lignes avec des mots-clés différents.

Je tente d'écrire une requête qui me donnera une liste de documents qui sont étiquetés avec un nombre arbitraire de mots-clés. Ma première tentative a été la suivante qui utilise l'instruction INTERSECT:

SELECT documentID FROM KeywordsToDocuments WHERE KeywordID=keyword1 
INTERSECT 
SELECT documentID FROM KeywordsToDocuments WHERE KeywordID=keyword2 
... 

Lorsque le ... peut être un nombre arbitraire de déclarations similaires pour d'autres mots-clés. Cette requête est construite par un script PHP dynamiquement. Ce que j'essaie de faire ici est de trouver tous les documents qui ont une association avec chaque mot-clé individuellement, puis de ces ensembles de résultats trouver l'intersection qui sera des documents qui sont associés à tous les mots-clés demandés.

Cependant, je viens d'apprendre que MySQL ne supporte pas l'instruction INTERSECT. Je cherchais des alternatives mais toutes les ressources que j'ai trouvées sur le remplacement de INTERSECT se sont concentrées sur le fait qu'il soit utilisé pour fusionner les résultats de deux tables différentes. Je ne peux pas voir un moyen dans ce cas de convertir à une autre déclaration comme INNER JOIN.

Comment une telle requête peut-elle fonctionner sans utiliser l'instruction INTERSECT pour permettre la compatibilité avec MySQL?

+0

Une jointure devrait bien sûr être la bonne. Quelles jointures as-tu déjà essayées qui n'ont pas abouti à ton résultat attendu? – ArSeN

+0

@ArSeN Je n'ai pas encore essayé de me joindre car je ne suis pas sûr de savoir comment accomplir la sémantique nécessaire en utilisant une jointure. C'est l'essence de mon problème – Vality

+0

@ splash58 Cela va chercher une seule ligne est égale à la fois non? Cela n'arrivera jamais. – Vality

Répondre

2

J'aime aborder ces questions en utilisant l'agrégation et une clause having:

SELECT documentID 
FROM KeywordsToDocuments 
WHERE KeywordID IN (keyword1, keyword2) 
GROUP BY documentID 
HAVING COUNT(*) = 2; 

Ce standard SQL et devrait fonctionner dans une base de données. En outre, en modifiant la clause HAVING, vous disposez d'une grande flexibilité sur la logique des combinaisons de mots-clés que vous recherchez.

+0

C'est merveilleux, je n'avais pas pensé à utiliser un HAVING. Merci, en effet, cela semble sensiblement plus propre que mon code original, y compris le «INTERSECT». Je vais accepter dans quelques instants. – Vality