Jag skulle skriva uteslutningsanslutningen utan underfrågor:
SELECT p.productid
FROM products p
INNER JOIN producttags AS t ON p.productid = t.productid
LEFT OUTER JOIN producttags AS x ON p.productid = x.productid
AND x.tag IN ('Motorcycle', 'Green')
WHERE p.active = 1
AND t.tag IN ( 'Ford', 'Black', 'Skateboard' )
AND x.productid IS NULL;
Se till att du har ett index över produkter över de två kolumnerna (aktiv, produkt-id) i den ordningen.
Du bör också ha ett index över produkttaggar över de två kolumnerna (productid, tag) i den ordningen.
En annan fråga jag kommer att behöva göra är något i stil med alla (Bil) eller (Skateboard) eller (Grön OCH Motorcykel) eller (Röd OCH Motorcykel).
Ibland är dessa komplexa förhållanden svåra för MySQL-optimeraren. En vanlig lösning är att använda UNION för att kombinera enklare frågor:
SELECT p.productid
FROM products p
INNER JOIN producttags AS t1 ON p.productid = t1.productid
WHERE p.active = 1
AND t1.tag IN ('Car', 'Skateboard')
UNION ALL
SELECT p.productid
FROM products p
INNER JOIN producttags AS t1 ON p.productid = t1.productid
INNER JOIN producttags AS t2 ON p.productid = t2.productid
WHERE p.active = 1
AND t1.tag IN ('Motorcycle')
AND t2.tag IN ('Green', 'Red');
PS:Din taggningstabell är inte en Entity-Attribute-Value-tabell.