SELECT pc.*
FROM products_categories pc
INNER JOIN products_categories_relations pcr
ON (pc.category_id = pcr.category_id)
INNER JOIN products p
ON (pcr.product_id = p.product_id AND published = 0)
EXCEPT
SELECT pc.*
FROM products_categories pc
INNER JOIN products_categories_relations pcr
ON (pc.category_id = pcr.category_id)
INNER JOIN products p
ON (pcr.product_id = p.product_id AND published != 0)
基本的に、公開済み = 0 の製品を持つカテゴリをクエリし、0 以外の公開済みの製品を持つすべてのセットから削除します。まさに必要なものが得られます。
公開済み = 0 の製品を含むカテゴリは、空のカテゴリと同じではないことに注意してください。空のカテゴリも必要な場合は、union all
.
EDIT:MySQLにはまだいくつかの基本的なSQL操作がないことを思い出したので、回避策があります:
SELECT pc.*
FROM products_categories pc
INNER JOIN products_categories_relations pcr
ON (pc.category_id = pcr.category_id)
INNER JOIN products p
ON (pcr.product_id = p.product_id AND published = 0)
WHERE pc.product_category_id NOT IN
(
SELECT distinct pc.product_category_id
FROM products_categories pc
INNER JOIN products_categories_relations pcr
ON (pc.category_id = pcr.category_id)
INNER JOIN products p
ON (pcr.product_id = p.product_id AND published != 0)
)
または、次のようにすることもできます。
SELECT * FROM
(
SELECT distinct pc.*
FROM products_categories pc
INNER JOIN products_categories_relations pcr
ON (pc.category_id = pcr.category_id)
INNER JOIN products p
ON (pcr.product_id = p.product_id AND published = 0)
) subQ1
LEFT OUTER JOIN
(
SELECT distinct pc.*
FROM products_categories pc
INNER JOIN products_categories_relations pcr
ON (pc.category_id = pcr.category_id)
INNER JOIN products p
ON (pcr.product_id = p.product_id AND published != 0)
) subQ2
ON subQ1.product_category_id = subQ2.product_category_id
WHERE subQ2.product_category_id IS NULL
最初の方が速いと思いますが、両方を試すことができます。