MySQL:计算属于活跃类别(以及可选的活跃子类别)的活跃产品
MySQL: Counting active products that belong to active categories (and optionally to active subcategories)
我正在使用 MySQL 5.6。我需要获取类别列表,其中包含产品 count
列。到目前为止,这是一项非常简单和微不足道的任务。这是它变得有点复杂的地方:
- 一个产品有一个类别,也可以有一个子类别(可选)。
- 类别、子类别和产品可以激活(
flg_public=1
)或禁用 (flg_public=NULL
).
因此,查询应该 return 包含产品数量的类别列表,满足这些要求:
- 如果某个类别被禁用,则它不得出现在列表中。
- 如果某个类别的子类别被禁用,则该子类别中的任何产品都不应计入相应类别的产品数量。
这是我当前的查询:
SELECT store_cat.id_cat AS id_cat,
store_cat.name AS name,
COUNT(DISTINCT store_product.id_product) AS q
FROM store_cat
LEFT JOIN store_product
ON store_product.id_cat = store_cat.id_cat
AND store_product.flg_public = 1
LEFT JOIN store_subcat
ON store_product.id_subcat = store_subcat.id_subcat
AND store_subcat.flg_public = 1
WHERE store_cat.flg_public = 1
GROUP BY store_cat.id_cat
我添加了一个 sqlfiddle:http://sqlfiddle.com/#!9/43461b/1
在这个例子中:
- 子类别裤子 属于类别衣服。
- 子类别 裤子
id_subcat=6
已被禁用 flg_public=0
- 子类别 裤子 只有 1 件产品处于活动状态,但由于该子类别已被禁用,因此不应在
count
查询中考虑这 1 件产品。
- 如您所见,有 4 个产品使用
id_cat=1
,但其中一个产品是 Pantalon Flash id_product=47
,属于子类别 裤子 id_subcat=6
已被禁用...但仍在考虑中...
衣服 类别在数量栏中 returning 4...但它应该是 3。以下是结果应显示的内容(红色变化):
有什么想法吗?谢谢!
你的问题是,因为你 LEFT JOIN
到 store_subcat
,甚至子类别 flg_public = 0
的产品也会包含在输出行中(尝试删除 GROUP BY
并更改为 SELECT *
并且您会看到 Pantalon Flash
在输出行中,即使它来自 store_subcat
的字段都是 NULL
因为它失败了 flg_public = 1
加入条件)。要解决此问题,您需要添加一项检查,以确保 store_product.id_subcat
是 NULL
,或者 store_subcat.id_subcat
不是 NULL
(当产品具有具有 flg_public = 1
的子类别。更新后的查询:
SELECT store_cat.id_cat AS id_cat,
store_cat.name AS name,
COUNT(DISTINCT store_product.id_product) AS q
FROM store_cat
LEFT JOIN store_product ON store_product.id_cat = store_cat.id_cat
AND store_product.flg_public = 1
LEFT JOIN store_subcat ON store_product.id_subcat = store_subcat.id_subcat
AND store_subcat.flg_public = 1
WHERE store_cat.flg_public = 1
AND (store_product.id_subcat IS NULL OR store_subcat.id_subcat IS NOT NULL)
GROUP BY store_cat.id_cat
输出:
id_cat name q
1 Clothes 3
2 Accesories 1
3 Snacks 2
4 Other 0
6 Furniture 0
7 Bags 0
9 Pencils 1
10 Medicines 0
11 Candy 0
请注意,Snacks
的正确计数实际上是 2,而不是 3。在 4 种零食中,Cookie wrappers
有 flg_public = 0
,因此不应包括在内,Pan de espárragos
有 id_subcat = 1
而那个 subcat 有 flg_public = 0
所以它也不应该被包括在内。所以在 4 种零食中,应该只包括 2 种。
SELECT store_cat.id_cat AS id_cat,
store_cat.name AS name,
COUNT(DISTINCT store_product.id_product) AS q
FROM store_cat
LEFT JOIN store_product
ON store_product.id_cat = store_cat.id_cat
-- AND store_product.flg_public = 1
LEFT JOIN store_subcat
ON store_product.id_subcat = store_subcat.id_subcat
-- AND store_subcat.flg_public = 1
WHERE store_cat.flg_public = 1
AND COALESCE(store_subcat.flg_public, 1)
GROUP BY store_cat.id_cat, store_cat.name ;
在 fiddle 中评论了最少的解释。
我正在使用 MySQL 5.6。我需要获取类别列表,其中包含产品 count
列。到目前为止,这是一项非常简单和微不足道的任务。这是它变得有点复杂的地方:
- 一个产品有一个类别,也可以有一个子类别(可选)。
- 类别、子类别和产品可以激活(
flg_public=1
)或禁用 (flg_public=NULL
).
因此,查询应该 return 包含产品数量的类别列表,满足这些要求:
- 如果某个类别被禁用,则它不得出现在列表中。
- 如果某个类别的子类别被禁用,则该子类别中的任何产品都不应计入相应类别的产品数量。
这是我当前的查询:
SELECT store_cat.id_cat AS id_cat,
store_cat.name AS name,
COUNT(DISTINCT store_product.id_product) AS q
FROM store_cat
LEFT JOIN store_product
ON store_product.id_cat = store_cat.id_cat
AND store_product.flg_public = 1
LEFT JOIN store_subcat
ON store_product.id_subcat = store_subcat.id_subcat
AND store_subcat.flg_public = 1
WHERE store_cat.flg_public = 1
GROUP BY store_cat.id_cat
我添加了一个 sqlfiddle:http://sqlfiddle.com/#!9/43461b/1
在这个例子中:
- 子类别裤子 属于类别衣服。
- 子类别 裤子
id_subcat=6
已被禁用flg_public=0
- 子类别 裤子 只有 1 件产品处于活动状态,但由于该子类别已被禁用,因此不应在
count
查询中考虑这 1 件产品。 - 如您所见,有 4 个产品使用
id_cat=1
,但其中一个产品是 Pantalon Flashid_product=47
,属于子类别 裤子id_subcat=6
已被禁用...但仍在考虑中...
衣服 类别在数量栏中 returning 4...但它应该是 3。以下是结果应显示的内容(红色变化):
有什么想法吗?谢谢!
你的问题是,因为你 LEFT JOIN
到 store_subcat
,甚至子类别 flg_public = 0
的产品也会包含在输出行中(尝试删除 GROUP BY
并更改为 SELECT *
并且您会看到 Pantalon Flash
在输出行中,即使它来自 store_subcat
的字段都是 NULL
因为它失败了 flg_public = 1
加入条件)。要解决此问题,您需要添加一项检查,以确保 store_product.id_subcat
是 NULL
,或者 store_subcat.id_subcat
不是 NULL
(当产品具有具有 flg_public = 1
的子类别。更新后的查询:
SELECT store_cat.id_cat AS id_cat,
store_cat.name AS name,
COUNT(DISTINCT store_product.id_product) AS q
FROM store_cat
LEFT JOIN store_product ON store_product.id_cat = store_cat.id_cat
AND store_product.flg_public = 1
LEFT JOIN store_subcat ON store_product.id_subcat = store_subcat.id_subcat
AND store_subcat.flg_public = 1
WHERE store_cat.flg_public = 1
AND (store_product.id_subcat IS NULL OR store_subcat.id_subcat IS NOT NULL)
GROUP BY store_cat.id_cat
输出:
id_cat name q
1 Clothes 3
2 Accesories 1
3 Snacks 2
4 Other 0
6 Furniture 0
7 Bags 0
9 Pencils 1
10 Medicines 0
11 Candy 0
请注意,Snacks
的正确计数实际上是 2,而不是 3。在 4 种零食中,Cookie wrappers
有 flg_public = 0
,因此不应包括在内,Pan de espárragos
有 id_subcat = 1
而那个 subcat 有 flg_public = 0
所以它也不应该被包括在内。所以在 4 种零食中,应该只包括 2 种。
SELECT store_cat.id_cat AS id_cat,
store_cat.name AS name,
COUNT(DISTINCT store_product.id_product) AS q
FROM store_cat
LEFT JOIN store_product
ON store_product.id_cat = store_cat.id_cat
-- AND store_product.flg_public = 1
LEFT JOIN store_subcat
ON store_product.id_subcat = store_subcat.id_subcat
-- AND store_subcat.flg_public = 1
WHERE store_cat.flg_public = 1
AND COALESCE(store_subcat.flg_public, 1)
GROUP BY store_cat.id_cat, store_cat.name ;
在 fiddle 中评论了最少的解释。