硬SQL查询 - 在另一个表中没有匹配的行或在另一个表中没有发布的项

时间:2013-10-25 10:09:24

标签: mysql sql

以下是我想要执行的SQL。我想避免做多次请求,我很确定这是可能的......

First table : products_categories (category_id, category_infos…)
Second table : products_categories_relations (product_id, category_id)
Third table : products (product_id, published, products_infos…)

我想查找所有空类别(其中没有产品)和仅包含未发布产品的类别。第二部分是我被困的地方。

SELECT pc.`category_id`
FROM `#__products_categories` AS pc
LEFT JOIN `#__products_categories_relations` pcr 
ON pc.`category_id` = pcr.`category_id`
WHERE pcr.`category_id` IS NULL

此查询为我提供了没有产品的类别,但我无法看到如何插入条件说:

  

“对于每个带有产品的类别,返回仅包含已公布的产品= 0”的

我的分析是:
如果A是查询“没有产品的类别”的结果 和B是“仅有未发布产品的类别”的结果 我需要A或B中的类别。

3 个答案:

答案 0 :(得分:0)

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

编辑: 正如我刚才提醒的那样,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

我怀疑第一个应该更快,但你可以尝试两者。

答案 1 :(得分:0)

UNION可能会帮到你:

SELECT pc.`category_id`
FROM `#__products_categories` AS pc
LEFT JOIN `#__products_categories_relations` pcr 
ON pc.`category_id` = pcr.`category_id`
WHERE pcr.`category_id` IS NULL
union
select category_id
from
(
SELECT pc.`category_id`,
sum(case when p.`published`=0 then 1 else 0 end) as unpublishedProductsCount,
count(*) as allProductsCount
FROM `#__products_categories` AS pc
INNER JOIN `#__products_categories_relations` pcr 
ON pc.`category_id` = pcr.`category_id`
INNER JOIN `#__products` p on p.product_id = pcr.product_id 
GROUP BY pc.`category_id`
) t
where t.allProductsCount = t.unpublishedProductsCount
;

union上方的上半部分是查询空类别的查询。

union下方的下半部分是一个查询,用于查找仅包含published=0

产品的类别

答案 2 :(得分:0)

SELECT pc.`category_id`
FROM `#__products_categories` AS pc
LEFT JOIN `#__products_categories_relations` pcr 
ON pc.`category_id` = pcr.`category_id`
LEFT JOIN (SELECT product_id, MAX(published) published
           FROM products
           GROUP BY product_id
           HAVING published = 0) p
ON pcr.product_id = p.product_id
WHERE pcr.`category_id` IS NULL OR p.product_id IS NOT NULL

子查询查找所有未发布的产品。我们加入,然后WHERE子句可以匹配不存在的产品与第一个测试,或未发布的产品与第二个测试匹配。