2 Stimmen

Einschränkung der Ergebnisse einer viele-zu-viele-Verbundabfrage

Ich habe drei Tabellen wie diese (vereinfachte Version):

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

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

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

Wie kann ich ObjectName und CategoryCode für alle Objekte auswählen, die nicht zu bestimmten CategoryCode gehören? Ich kann nicht einfach eine WHERE-Klausel zu der gejointen Abfrage auf allen drei Tabellen hinzufügen, da die beabsichtigte Einschränkung ignoriert wird, solange ein Objekt zu mindestens einem erlaubten CategoryCode gehört.

EDIT: Ich muss auch CategoryCode aus der Tabelle Category auswählen, ein Select nur auf der Tabelle Object reicht nicht aus

1voto

Roland Bouman Punkte 29957

Hier ist eine Lösung für 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
)

Mit wenig Aufwand kann dies in eine äquivalente NOT IN-Unterabfrage umgeschrieben werden (nicht gezeigt)

In mySQL können Unterabfragen, insbesondere korrelierte Unterabfragen wie die EXISTS- und NOT IN-Lösungen, ziemlich langsam sein. Eine Alternative besteht darin, es mit einem LEFT JOIN und GROUP BY zu versuchen:

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

0voto

rael_kid Punkte 11140
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')

Nicht getestet, aber dies sollte die Namen aller IDs der Objekte abrufen, die nicht mit einem bestimmten CategoryCode verbunden sind

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X