Prüfung auf mehrere Kriterien

Kürzlich erreichte mich die Anfrage aus unserer PASS-Gruppe, wie man am effektivsten aus einer Menge von Lieferungen diejenigen herausfinden könnte, wo mehrere Kriterien erfüllt sein müssten. Eine Kombination von Joins oder AND-Bedingungen schien nicht der richtige Weg zu sein.

Die Fragestellung

Gegeben ist eine Menge von Lieferungen, die sich aus Artikeln und Losen zusammensetzt. Ein Los ist hier vergleichbar mit einer Charge. Gesucht werden z. B. alle Lieferungen, in denen der Artikel 1 aus Los 101 und der Artikel 2 aus Los 102 enthalten sind.

Die Lösung

Man speichert zuerst die gewünschten Artikel und Lose in einer Hilfstabelle ab, die unsere Suchmaske darstellen soll. Danach verknüpft man die Lieferungen mit der Suchmaske und zählt, wie oft jede Lieferung dort einen Treffer hatte. Stimmt am Ende die Anzahl der Treffer mit der Anzahl der Bedingungen in der Suchmaske überein, hat man eine Lieferung gefunden.

Das T-SQL Skript

Das Skript ist weitestgehend selbsterklärend und besteht überwiegend aus der Zusammenstellung der Beispieldaten. Am Ende wird alles mit einer CTE (Common Table Expression) voranalysiert und dann ausgewertet. Die Kombination von Lieferung, Artikel und Los in der Ausgangstabelle ist eindeutig.

DECLARE @tab AS TABLE (Lieferung INT, Artikel INT, Los INT);

INSERT INTO @tab(Lieferung, Artikel, Los) VALUES (1, 1, 101);
INSERT INTO @tab(Lieferung, Artikel, Los) VALUES (1, 1, 102);
INSERT INTO @tab(Lieferung, Artikel, Los) VALUES (1, 3, 101);
INSERT INTO @tab(Lieferung, Artikel, Los) VALUES (1, 2, 102);
INSERT INTO @tab(Lieferung, Artikel, Los) VALUES (2, 1, 101);
INSERT INTO @tab(Lieferung, Artikel, Los) VALUES (2, 1, 102);
INSERT INTO @tab(Lieferung, Artikel, Los) VALUES (2, 3, 101);

DECLARE @Suchmaske AS TABLE (Artikel INT, Los INT);
INSERT INTO @Suchmaske(Artikel, Los) VALUES(1, 101);
INSERT INTO @Suchmaske(Artikel, Los) VALUES(2, 102);

-- Prüfung mit CTE und Join
WITH Vorberechnung AS
(SELECT Lieferung, COUNT(*) AS Anzahl
FROM @tab t1
INNER JOIN @Suchmaske s1 ON t1.Artikel = s1.Artikel AND t1.Los = s1.Los
GROUP BY Lieferung
)
SELECT DISTINCT Lieferung
FROM Vorberechnung v
WHERE v.Anzahl = (SELECT COUNT(*) FROM @Suchmaske)
;