在我的 MySQL 数据库中,我有一个存储文章和类别关联的表,列是 category_id 和 product_id。因此,属于类别#3 和#6 的文章#5 具有行(3,5)(6,5)。
现在我需要获取类别 1 和 6 中的文章数。获取一个类别中的文章数很容易,SELECT count(category_id) from s_a_c where category_id=1
但是如何扩展此查询以检查是否有两只猫?
这是一种有两种联接的方法(您要搜索的每个类别都有一个联接):
SELECT COUNT(1)
FROM articles
INNER JOIN s_a_c c1 ON articles.product_id = c1.product_id
AND c1.category_id = 1
INNER JOIN s_a_c c2 ON articles.product_id = c2.product_id
AND c2.category_id = 6
这是使用HAVING
子句的另一种方式。s_a_c
派生表从类别 1 和 6中提取所有产品,同时具有 ( COUNT(1) = 2
)。这利用了{product_id, category_id}
独一无二的事实:
SELECT COUNT(1)
FROM
(
SELECT product_id
FROM s_a_c
WHERE category_id IN (1,6)
GROUP BY product_id
HAVING COUNT(1) = 2
) x
您需要按产品对表进行分组,然后过滤符合您所需条件的组(使用HAVING
子句,该子句在分组后评估,而WHERE
子句在分组前评估):
SELECT COUNT(*) FROM (
SELECT article_id
FROM s_a_c
WHERE category_id IN (1,6)
GROUP BY product_id
HAVING COUNT(DISTINCT category_id) = 2
) t
如果(product_id,category_id)
保证是唯一的(例如,通过UNIQUE
键强制执行的唯一性约束),您可以使用性能更高COUNT(*)
的COUNT(DISTINCT category_id)
.
如果您需要在组过滤器上实现更复杂的逻辑,您可以利用 MySQL 缺乏真正的布尔类型,因此:
SELECT article_id
FROM s_a_c
WHERE category_id IN (1,3,6)
GROUP BY product_id
HAVING SUM(category_id = 1)
AND SUM(category_id = 6)
AND NOT SUM(category_id = 3)
请注意,我继续包含一个WHERE
子句,以便 MySQL 可以使用索引来避免全表扫描。
获取两个类别(一和二)中的所有文章(可能有重复)
SELECT count(category_id) from s_a_c where category_id=1 or category_id=2
获取两个类别(一和二)中的所有文章(不重复)
SELECT count(category_id) FROM s_a_c WHERE category_id=1 or category_id=2 GROUP BY article_id
编辑:误读 - 如果存在于任一或类别中,则此原始查询确实存在:
SELECT COUNT(*) FROM s_a_c WHERE category_id IN (1,6);
两个类别中存在的正确查询:
SELECT COUNT(*) FROM s_a_c WHERE category_id = 1 AND category_id 6;
TBH,这一切都还为时过早,没有看到s_a_c
.