Scriverei il join di esclusione senza sottoquery:
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;
Assicurati di avere un indice sui prodotti nelle due colonne (active, productid) in quell'ordine.
Dovresti anche avere un indice sui producttag sulle due colonne (productid, tag) in quell'ordine.
Un'altra domanda che dovrò fare è qualcosa come tutti (Auto) o (Skateboard) o (Verde E Moto) o (Rosso E Moto).
A volte queste condizioni complesse sono difficili per l'ottimizzatore MySQL. Una soluzione alternativa comune consiste nell'utilizzare UNION per combinare query più semplici:
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:la tua tabella di tagging non è una tabella Entity-Attribute-Value.