Rolf B: MySQL: Schnittmengen abfragen

Beitrag lesen

Hallo Timo,

die Standardlösung wäre ein INTERSECT - aber den kennt MySQL nicht. Man kann ihn aber mit einem Subselect oder einem Join nachbauen.

Welche Lösung genau passt, hängt von der übrigen Aufgabe ab. Geht es Dir nur um die Artikel-ID?

Möglichkeit 1: Subselect. Sofern ein Artikel nur eine Row mit filterValue=4 hat, könnte sie am effizientesten sein.

SELECT a1.artikelID
FROM artikel a1
WHERE a1.kategorie = 1
  AND a1.filterValue = 4
  AND EXISTS (SELECT * 
              FROM artikel a2 
              WHERE a2.artikelId = a1.artikelId 
                AND a2.kategorie = 1
                AND filterValue IN (2, 3)

Möglichkeit 2: Inner Join. Würde in deinem Beispiel für artikelID=1234 zwei Zeilen liefern, darum muss ein DISTINCT dazu. Man müsste EXPLAINs laufen lassen, aber ich würde annehmen, dass diese Variante weniger performant ist. Kommt drauf an, wie gut der SQL Optimizer in deiner DB ist.

SELECT DISTINCT artikelId
FROM artikel a1 JOIN artikel a2
     ON a1.artikelId=a2.artikelId
     AND a1.kategorie=1
     AND a1.filterValue=4
     AND a2.kategorie=1
     AND a2.filterValue=2 IN (2, 3)

Für beide Queries gilt: Ob bei a2 ebenfalls die Kategorie abgefragt werden muss, hängt von deinen Daten ab. Ist die Kategorie ein Oberbegriff zu den Artikeln, so dass alle Rows einer ArtikelID die gleiche Kategorie haben, oder kann es innerhalb einer ArtikelId Rows mit unterschiedlichen Kategorien geben?

In beiden Fällen ist zu empfehlen, dass es einen Index gibt, der ArtikelId und FilterValue enthält. Damit lässt sich die Query durch Indexabfragen ausführen und es ist kein Zugriff auf den Data-Teil der Table nötig.

Rolf

--
sumpsi - posui - obstruxi