mySql 使用 HAVING COUNT(DISTINCT) 和 AND 和 OR(包含和排除子句)进行查询
mySql query with HAVING COUNT(DISTINCT) with AND and OR (inclusive and exclusive clause)
我必须修改 Wordpress 站点内的 mySql 自定义查询。
我将尝试向您解释我的问题,将查询简化为真正需要知道的问题。
tablecms_posts(别名'p')内连接到cms_term_relationship table(别名'term_rel')。
我需要找到所有包含 term_rel.term_taxonomy 值的 cms_posts 211,210,10,9.
我当前的查询是:
SELECT SQL_CALC_FOUND_ROWS
p.id
FROM cms_posts p
INNER JOIN cms_term_relationships term_rel
ON term_rel.object_id = p.id
WHERE
term_rel.term_taxonomy_id IN (211,210,10,9)
GROUP BY p.id
HAVING
COUNT(DISTINCT term_rel.term_taxonomy_id) = 4
LIMIT 0, 50
COUNT(DISTINCT 确保严格遵守我在 WHERE 子句中询问的所有关系。
一切正常。
但是我需要修改查询!
我需要拆分 WHERE 子句。我试着打个比方。
我需要在 211 AND 210 和 10 OR 9.
我搜索所有这些帖子组合:
211, 210, 10
211, 210, 9
所以我需要 211 和 210 都需要 ,但是 10 OR 9 也只需要出现 1 次。
详细地说,我需要我的帖子属于 X、Y、Z 类别,并且至少属于 A、B 或 C 类别。 X、Y、Z类别是排他性的; A、B、C均含。
这个问题不是那么容易解释的,而且我糟糕的英语也无济于事。
我希望有人能理解我的英语甚至我的问题 :D
带有 count distinct
的 having
子句仍然是一种有效的方法。例如,您可以做的是使用 case 表达式将 ID 9 和 10 视为相同,从而允许您继续计算所需的不同数字 ID。例如:
SELECT SQL_CALC_FOUND_ROWS
p.id
FROM vf_posts p
INNER JOIN vf_term_relationships term_rel
ON term_rel.object_id = p.id
WHERE
term_rel.term_taxonomy_id IN (211,210,10,9)
GROUP BY p.id
HAVING
COUNT(DISTINCT CASE term_rel.term_taxonomy_id
WHEN 9 THEN 10
ELSE term_rel.term_taxonomy_id
END) = 4 -- Here!
LIMIT 0, 50
感谢 Mureinik 的回答,但如果我尝试实现您的代码,使用 case 表达式似乎不起作用。如果我很好地理解你的目标,那么在那个案例中,所有 'inclusive terms',但第一个,都没有被 COUNT(DISTINCT) 考虑。我可能没有以正确的方式实现你的代码,但结果不是够用了。
但也许我有解决办法。
让我试着给你一个更好的解释:
- exclusive_terms.term_taxonomy_id 是要搜索的字段;
- 对于 exclusive_terms.term_taxonomy_id
,有一个 独占值 的列表
- 还有 包含值 的列表 exclusive_terms.term_taxonomy_id
如果用户搜索 exclusive_terms.term_taxonomy_id 的 211、210、9、217、215、218、10 个值,我首先需要做的是将排他性与包容性分开。
我获得了 2 个列表:
- 独家 211, 210
- 包括 9、217、215、218、10
之后,我可以编写此查询,在同一字段上使用 2 JOINS,但使用 2 个不同的别名调用结果字段,然后仅在独家条款。
SELECT SQL_CALC_FOUND_ROWS p.id,
FROM cms_posts p
INNER JOIN cms_term_relationships exclusive_terms ON exclusive_terms.object_id = p.id
INNER JOIN cms_term_relationships inclusive_terms ON inclusive_terms.object_id = p.id
WHERE
exclusive_terms.term_taxonomy_id IN (211, 210)
AND
inclusive_terms.term_taxonomy_id IN (9, 217, 215, 218, 10)
GROUP BY p.id
HAVING
COUNT(DISTINCT exclusive_terms.term_taxonomy_id) = 2
LIMIT 0, 50
好像有用!
我必须修改 Wordpress 站点内的 mySql 自定义查询。 我将尝试向您解释我的问题,将查询简化为真正需要知道的问题。
tablecms_posts(别名'p')内连接到cms_term_relationship table(别名'term_rel')。
我需要找到所有包含 term_rel.term_taxonomy 值的 cms_posts 211,210,10,9.
我当前的查询是:
SELECT SQL_CALC_FOUND_ROWS
p.id
FROM cms_posts p
INNER JOIN cms_term_relationships term_rel
ON term_rel.object_id = p.id
WHERE
term_rel.term_taxonomy_id IN (211,210,10,9)
GROUP BY p.id
HAVING
COUNT(DISTINCT term_rel.term_taxonomy_id) = 4
LIMIT 0, 50
COUNT(DISTINCT 确保严格遵守我在 WHERE 子句中询问的所有关系。
一切正常。
但是我需要修改查询!
我需要拆分 WHERE 子句。我试着打个比方。
我需要在 211 AND 210 和 10 OR 9.
我搜索所有这些帖子组合:
211, 210, 10
211, 210, 9
所以我需要 211 和 210 都需要 ,但是 10 OR 9 也只需要出现 1 次。
详细地说,我需要我的帖子属于 X、Y、Z 类别,并且至少属于 A、B 或 C 类别。 X、Y、Z类别是排他性的; A、B、C均含。
这个问题不是那么容易解释的,而且我糟糕的英语也无济于事。
我希望有人能理解我的英语甚至我的问题 :D
带有 count distinct
的 having
子句仍然是一种有效的方法。例如,您可以做的是使用 case 表达式将 ID 9 和 10 视为相同,从而允许您继续计算所需的不同数字 ID。例如:
SELECT SQL_CALC_FOUND_ROWS
p.id
FROM vf_posts p
INNER JOIN vf_term_relationships term_rel
ON term_rel.object_id = p.id
WHERE
term_rel.term_taxonomy_id IN (211,210,10,9)
GROUP BY p.id
HAVING
COUNT(DISTINCT CASE term_rel.term_taxonomy_id
WHEN 9 THEN 10
ELSE term_rel.term_taxonomy_id
END) = 4 -- Here!
LIMIT 0, 50
感谢 Mureinik 的回答,但如果我尝试实现您的代码,使用 case 表达式似乎不起作用。如果我很好地理解你的目标,那么在那个案例中,所有 'inclusive terms',但第一个,都没有被 COUNT(DISTINCT) 考虑。我可能没有以正确的方式实现你的代码,但结果不是够用了。
但也许我有解决办法。
让我试着给你一个更好的解释:
- exclusive_terms.term_taxonomy_id 是要搜索的字段;
- 对于 exclusive_terms.term_taxonomy_id
,有一个 独占值 的列表
- 还有 包含值 的列表 exclusive_terms.term_taxonomy_id
如果用户搜索 exclusive_terms.term_taxonomy_id 的 211、210、9、217、215、218、10 个值,我首先需要做的是将排他性与包容性分开。
我获得了 2 个列表:
- 独家 211, 210
- 包括 9、217、215、218、10
之后,我可以编写此查询,在同一字段上使用 2 JOINS,但使用 2 个不同的别名调用结果字段,然后仅在独家条款。
SELECT SQL_CALC_FOUND_ROWS p.id,
FROM cms_posts p
INNER JOIN cms_term_relationships exclusive_terms ON exclusive_terms.object_id = p.id
INNER JOIN cms_term_relationships inclusive_terms ON inclusive_terms.object_id = p.id
WHERE
exclusive_terms.term_taxonomy_id IN (211, 210)
AND
inclusive_terms.term_taxonomy_id IN (9, 217, 215, 218, 10)
GROUP BY p.id
HAVING
COUNT(DISTINCT exclusive_terms.term_taxonomy_id) = 2
LIMIT 0, 50
好像有用!