7
votes

Mysql Sélectionnez où dans beaucoup de

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 article_category code> qui a un ID code>, article_id code> et Catégorie_id CODE> champ.

Je souhaite sélectionner tous les articles qui ont uniquement les catégories avec ID 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>

Par exemple, il s'agit d'un échantillon de sortie de la SQL ( avec des catégories présentées à des fins descriptives forts> ). Vous pouvez voir que lorsque la requête a sélectionné l'article avec ID d'ID de 10 code>, il a également sélectionné l'article avec un identifiant de 11 code> malgré une catégorie supplémentaire. P> xxx pré>

Il s'agit de la sortie que je veux réaliser à partir de la sélection d'articles avec uniquement des catégories 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
)


1 commentaires

Regardez la question suivante. Ressemble au même problème à moi Stackoverflow.com/Questtions/84688117/...


10 Réponses :


0
votes

J'aime aborder ces requêtes en utilisant groupe par code> et ayant code>. Voici un exemple: xxx pré>

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:

having sum(category_id in (1, 2, 3)) = count(*) and
       count(*) = 3


2 commentaires

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 . L'avantage de cette approche est qu'il peut décrire de manière flexible les critères d'inclusion et d'exclusion.



0
votes

Peut-être, quelque chose comme: xxx


0 commentaires

0
votes

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


0 commentaires

1
votes

Vous pouvez avoir laissé rejoindre 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)

Aussi avec cette approche, vous pouvez facilement rendre cette dynamique de requête avec PHP ou toute autre langue P>

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'
)


1 commentaires

Cela pourrait probablement utiliser une explication :-).



0
votes
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

0 commentaires

3
votes

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'


2 commentaires

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.



0
votes

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


0 commentaires

0
votes

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))


0 commentaires

0
votes

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)
)


0 commentaires

1
votes

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;


0 commentaires