Zielstellung

Häufig gibt es die Situation, und sei es nur zur Datenanalyse oder Fehlersuche, dass man die Datensätze in einer MySQL-Tabelle finden möchte, die es in einem Abfrageresultat gibt, aber nicht in dem anderen.

Z.B.: Sie wollen alle Produkt-Ids/Artikelnummern von Produkten finden, die es in einer Artikelgruppe gibt aber nicht in der anderen.

Umsetzung / Lösung per MySQL

Für die Lösung sind 3 Bausteine notw.

  1. Damit alle DS mit einer einzigen Abfrage aufgelistet werden, die es in der einen Artikelgruppe nicht gibt bzw. in der anderen nicht gibt, führen wir zwei Teilabfragen durch, die dann mit UNION zusammengeführt werden und als eine gemeinsame Ergebnisliste ausgegeben werden. Hier könnten weitere Teilergebnislisten angefügt werden z.B. für weiter Artikelgruppen.
  2. Innerhalb dieser Teilabfragen für jede Artikelgruppe erstellen wir zunächst eine Trefferliste über alle gefundenen DS die entweder der einen oder anderen ArtGrp angehören. Dazu nutzen wir zwei Teilabfrage, die mit UNION ALL zusammengefügt werden. Dann reduzieren wir diese Treffer auf je max. 1 DS pro artnr durch Verwendung von GROUP BY artnr. Das ist unsere Gesamtmenge.
  3. An diese gruppierte Gesamttrefferliste fügen wir nun per LEFT JOIN die Datensätze der zu prüfenden ArtikelGruppe an. Wir suchen als die Vergleichs-Teilmenge. Dort wo es keinen Treffer gibt, wird das Feld artnr mit NULL <null> geschrieben. Genau nach diesem NULL fragen wir dann ab und lassen uns per artnr IS NULL als Trefferliste alle Datensätze zeigen, die keine ArtNr aus dem LEFT JOIN bekommen haben.

Hier mal ein Codebeispiel, die Umsetzung beispielsweise erfolgen kann:



SELECT * FROM 
	(
		SELECT a.id A_id, a.artnr A_artnr, 30 AS fehlt_in 
		FROM (
				SELECT * FROM products x WHERE x.artgrp = 10
				UNION ALL
				SELECT * FROM products x WHERE x.artgrp = 30
				GROUP BY x.artnr
				) AS a
			LEFT JOIN (
				SELECT y.artnr FROM products y WHERE y.art_grp = '056' AND y.kat_id = 30) AS
				b on a.artnr = b.artnr
		WHERE b.artnr IS NULL
	UNION 
		SELECT c.id B_id, c.artnr B_artnr, 10 AS fehlt_in FROM (
				SELECT * FROM products x WHERE x.artgrp = 10
				UNION ALL
				SELECT * FROM products x WHERE x.artgrp = 30
				GROUP BY x.artnr
				) AS c
			LEFT JOIN (
				SELECT y.artnr FROM products y WHERE y.artgrp = 10) AS
				d on c.artnr = d.artnr
		WHERE d.artnr IS NULL
	)
	AS result
;

Im obigen Beispiel wird die Suche komplett innerhalb einer Tabelle vorgenommen, weshalb hier konsequent mit Aliases gearbeitet wird. Natürlich lassen sich auch mehrere Tabellen mitanander vergleichen oder per LEFT JOIN eine Verknüpfung zu einer weiteren Beziehungstabelle z.B. für Produktkategorien oder -preisen etc. herstellen.