J'ai des problèmes avec une requête SQL. Mon schéma décrit un grand nombre de relations entre articles dans les articles de la table code> et les catégories dans la table code> code> - avec la table intermédiaire Je souhaite sélectionner tous les articles qui ont uniquement les catégories avec ID Par exemple, il s'agit d'un échantillon de sortie de la SQL ( Il s'agit de la sortie que je veux réaliser à partir de la sélection d'articles avec uniquement des catégories article_category code> qui a un
ID code>,
article_id code> et
Catégorie_id CODE> champ.
1 Code> et
2 code>. Malheureusement, cette requête sélectionnera également tous les articles qui disposent de ces catégories en plus des autres. P>
10 code>, il a également sélectionné l'article avec un identifiant de
11 code> malgré une catégorie supplémentaire. P> xxx pré>
1 code> et
2 code>. p>
SELECT articles.id
FROM articles
WHERE EXISTS (
SELECT 1
FROM article_category
WHERE articles.id = article_id AND category_id IN (1,2)
GROUP BY article_id
)
10 Réponses :
J'aime aborder ces requêtes en utilisant chaque condition dans la clause code> code> est testant la présence d'une des catégories. P> Je trouve que Cette approche est la plus flexible pour répondre à de nombreux types différents de problèmes "définis dans les ensembles". p> EDIT: P> Une légère variation de ce qui précède pourrait être plus facile à générer: groupe par code> et
ayant code>. Voici un exemple:
having sum(category_id in (1, 2, 3)) = count(*) and
count(*) = 3
Quelle est la facilité que cela sera-t-il pour des cas avec plus de deux catégories? J'ai besoin de pouvoir générer cette requête de manière dynamique à l'aide d'un script.
@Georgerobinson. . . Vous devez simplement ajouter une autre condition à la clause code>. L'avantage de cette approche est qu'il peut décrire de manière flexible les critères d'inclusion et d'exclusion.
Peut-être, quelque chose comme:
ressemble à une solution simple pour cela pourrait être le suivant:
SELECT ac.article_id , SUM(ac.category_id IN (1, 2)) AS nb_categories , COUNT(ac.category_id) AS nb_all_categories FROM article_categories ac GROUP BY ac.article_id HAVING nb_categories=2 AND nb_all_categories=2
Vous pouvez avoir laissé rejoindre Aussi avec cette approche, vous pouvez facilement rendre cette dynamique de requête avec PHP ou toute autre langue P> catégorie_id code> sur
catégorie.id code> puis group_concat pour obtenir toutes les catégories, comme vous l'avez écrit dans l'explication (1ère table) et que d'utiliser
ayant code> correspondant à n'importe quel jeu de jeu. ('1,2' de l'exemple)
SELECT articles.id
FROM articles
WHERE EXISTS (
SELECT GROUP_CONCAT(c.id) AS grp
FROM article_category
LEFT OUTER JOIN categories AS c ON c.id = article_category.category_id
WHERE articles.id = article_id
GROUP BY article_id
HAVING grp = '1,2'
)
Cela pourrait probablement utiliser une explication :-).
SELECT articles.id FROM articles INNER JOIN articles_category ac ON articles.id = ac.article_id WHERE articles.id IN ( SELECT ac1.article_id FROM article_category ac1 WHERE ac1.category_id = 1; ) AND ac.article_id = 2; AND articles.id NOT IN ( SELECT ac2.article_id FROM article_category ac2 WHERE ac2.category_id NOT IN (1, 2) ) Far from the prettiest one I have written.Basically, it limits first by ID that have a category id of 1, then it makes sure the records have a category of 2 as well, finally, it makes sure that it does not have any other categories
En supposant que vous souhaitez plus que l'ID de l'article:
SELECT article_id FROM article_category GROUP BY article_id HAVING GROUP_CONCAT(DISTINCT category_id ORDER BY category_id SEPARATOR ',') = '1,2'
Je ne veux pas être impoli mais comment va-t-il différent de ma réponse?
plusieurs différences. 1) NON Où existe. 2) Pas de sous-sélection. 3) Aucune hypothèse selon laquelle les catégories_id ne sont pas répétées (probablement une hypothèse sûre mais distincte l'élimine). 4) Aucune hypothèse selon laquelle la catégorie_id sera dans la séquence ascendante dans la base de données (commande en élimine cette hypothèse). 5) Si l'ID d'article est tout ce qui est requis, pas de jointure.
Pour aider à simplement sans changer votre requête, je pense que la logique a un bug. Vous ne voulez pas d'articles où un CATTEGEGORY 1,2 existe. Vous avez besoin d'articles où n'existe pas de catégories différentes de 1 et 2. Merci et regarde p>
Dans SQL Server, je le ferais avec un intersect et une sauf. Dans MySQL, essayez ceci:
SELECT DISTINCT article_id FROM article_category WHERE category_id=1 AND article_id IN (SELECT article_id FROM article_category WHERE category_id=2) AND article_id NOT IN (SELECT article_id FROM article_category WHERE category_id NOT IN (1,2))
Utilisez cette requête SQL.
SELECT articles.id FROM articles WHERE articles.id in ( SELECT * FROM article_category,articles WHERE article_category.articles.id = articles.article_id AND article_category.category_id IN (1,2) )
Veuillez utiliser ci-dessous la requête Vous pouvez faire la chose en utilisant une requête simple.
SELECT a.id, a.name FROM articles a, categories c, articles_categories ac WHERE a.id = ac.article_id AND c.id = ac.category_id AND c.id = 1 OR c.id = 2;
Regardez la question suivante. Ressemble au même problème à moi Stackoverflow.com/Questtions/84688117/...