2010-02-16 5 views
2

J'ai trois tables comme celle-ci (version simplifiée):Restriction des résultats d'une de plusieurs à plusieurs rejoint requête

Object 
--------------- 
ID | ObjectName 
--------------- 

Category 
----------------- 
ID | CategoryCode 
----------------- 

ObjectCategory 
--------------------- 
ObjectID | CategoryID 
--------------------- 

Comment puis-je choisir ObjectName et CategoryCode pour tous les objets qui se font pas appartiens à certains CategoryCode s? Je ne peux pas simplement ajouter une clause WHERE à la requête JOIN sur les trois tables, car elle ignorera la restriction voulue tant qu'un objet appartient à au moins un objet autorisé CategoryCode.

EDIT: Je dois aussi sélectionner CategoryCode de la table Category, une sélection uniquement sur la table Object ne suffit pas

+1

Je pense que vous * pouvez * utiliser une jointure, et je pense que ce sera plus rapide que le PAS EXISTE et non pas dans des solutions. L'astuce consiste à utiliser un OUTER JOIN et à inclure les codes de catégorie que vous souhaitez rechercher dans la condition ON, et utiliser le WHERE pour voir si la catégorie d'objet correspondante est NULL (c'est-à-dire, si elle n'existe pas). Voir ma réponse ci-dessous –

+0

Relisant votre question, je me demandais - voulez-vous dire que vous ne voulez pas voir les objets dans le cas où ils correspondent à une ou toutes les catégories que vous fournissez? –

+0

Je dois exclure tous les objets qui correspondent à l'une des catégories fournies –

Répondre

0
SELECT ObjectName 
FROM Objects 
    WHERE ObjectID NOT IN (
      SELECT ObjectID 
      FROM ObjectCategory AS a 
      JOIN Category AS b 
       ON a.CategoryID = b.CategoryID 
      WHERE CategoryCode = 'yourcodehere') 

ai pas testé, mais cela ne devrait obtenir les noms de tous les ID de la Les objets qui ne sont pas connectés à un certain CategoryCode

+0

Je dois aussi sélectionner CategoryCode –

+0

Oui, j'ai vu cela dans votre édition ... :) Vous pouvez d'abord sélectionner les codes distincts, puis les boucler avec cette requête, ou vous pouvez utiliser le code de Roland ci-dessous. –

1

Voici une solution pour NOT EXISTS

select  o1.*, c1.* 
from   object   o1 
inner join object_category oc1 
on   o1.id   = oc1.object_id 
inner join category c1 
on   oc1.category_id = c1.id 
where not exists (
      select null 
      from  object_category oc2 
      inner join category  c2 
      on   oc2.category_id = c2.id 
      where  c2.name in ('code1', 'code1') 
      and  oc2.object_id = o1.id 
) 

Avec peu d'effort, ceci peut être réécrit en une sous-requête NOT IN équivalente (non montrée)

Dans mySQL, les sous-requêtes, en particulier les sous-requêtes corrélées comme les solutions EXISTS et NOT IN peuvent être assez lentes. Alternative est d'essayer LEFT JOIN et GROUP BY:

select  o1.*, c1.* 
from  object     o1 
inner join object_category  oc1 
on   o1.id = oc1.object_id 
inner join category    c1 
on   oc1.category_id = c1.id 
left join object_category  oc2 
on   o1.id = oc2.object_id 
left join category    c2 
on   oc2.category_id = c2.id 
and   c2.name in ('code1', 'code1') 
group by o1.id, c1.id 
having  count(c2.id) = 0 
+0

Je dois ** exclure ** certaines catégories –

+0

kemp: avez-vous essayé? cette requête exclut les catégories çode1 et code2 –

+0

Je reçois 'NULL' dans le champ' CategoryCode' –

Questions connexes