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 distincthaving 子句仍然是一种有效的方法。例如,您可以做的是使用 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

好像有用!