2012-09-12 77 views
1

这是那些日子之一,我只是无法弄清楚这一点。Where子句等于一个字段,不等于另一个

我有以下查询:

SELECT * FROM wp_posts 
JOIN wp_term_relationships ON wp_term_relationships.object_id = wp_posts.ID 
WHERE term_taxonomy_id = 80 

显然,这种选择所有处于类别ID 80.我需要做的是选择所有在80类,但不是什么职位的职位在类别109

我已经试过这一点,但它只是选择从类别80

SELECT * FROM wp_posts 
JOIN wp_term_relationships ON wp_term_relationships.object_id = wp_posts.ID 
WHERE term_taxonomy_id = 80 
AND term_taxonomy_id = 109 

这里同样职位的表结构:

wp_posts 

| ID | 
------------ 
| 1  | 
| 2  | 

wp_term_relationships 

| object_id | term_taxonomy_id | 
|-----------|------------------| 
|  1  |  80   | 
|  2  |  80   | 
|  1  |  109  | 

OBJECT_ID匹配POST_ID

查询应该只因为ID 1返回ID 2在这两个80和109

我知道我这样做了一百万次,但我就是”为了我的生活得到这个工作。任何帮助?

回答

1

这里有一个办法:

SELECT p.* 
    FROM wp_posts p 
    JOIN wp_term_relationships t 
    ON t.object_id = p.ID AND t.term_taxonomy_id = 80 
    LEFT 
    JOIN wp_term_relationships n 
    ON n.object_id = p.ID AND n.term_taxonomy_id = 109 
WHERE n.object_id IS NULL 

这将使用LEFT OUTER JOIN对长期关系表(别名为n ),找到类别109中的匹配行,但随后排除找到匹配项的任何行(通过中的条件条款,从那些不在类别109

在SQL说法wp_posts返回所以疗法行,我们把这个操作,作为“反连接”。

注意:如果(object_id,term_taxonomy_id)不唯一,例如,您在wp_term_relationships中有两个(或多个)行(object_id = 2,term_taxonomy_id = 80),则此查询确实有可能返回“重复”行。


一般来说,在MySQL中,我们发现JOIN操作(包括反连接操作)通常优于子查询。

另一种选择(这是很可能不执行,以及之前的查询):

SELECT p.* 
    FROM wp_posts p 
WHERE EXISTS 
     (SELECT 1 
      FROM wp_term_relationships t 
      WHERE t.object_id = p.ID 
      AND t.term_taxonomy_id = 80 
     ) 
    AND NOT EXISTS 
     (SELECT 1 
      FROM wp_term_relationships n 
      WHERE n.object_id = p.ID 
      AND n.term_taxonomy_id = 109 
     ) 

注:这可能是MySQL生成此查询(包括相同的执行计划的加入和反连接操作)和前一个一样。您需要在查询上运行EXPLAIN以查看执行计划,并测试其中一个是否比另一个“更快”。

还有其他的方法。性能将取决于可用的(合适的)索引,数据分布和生成的执行计划。

+0

+1,但回复:“一般情况下,在MySQL中,我们发现,JOIN操作(包括反连接操作)通常优于子查询“:对于某些类型的子查询,这是正确的,但根据我的理解,最近版本的MySQL在识别IN(...)和NOT IN(...)作为半连接和反连接时没有任何问题(分别)并相应地优化。 – ruakh

+0

@ruakh ...这就是为什么我建议'EXPLAIN'输出和测试是合适的。它绝对取决于哪个版本的MySQL。例如,在MySQL 5.1中,NOT IN(子查询)不会产生与等价的“LEFT JOIN ... WHERE ... IS NOT NULL”查询相同的计划。 (有趣的是,'LEFT JOIN'查询在解释输出中显示''; not exists'',而一个'NOT EXISTS'查询显示了一个与'NOT IN'查询相同的计划,这两个查询都显示了'DEPENDENT SUBQUERY'解释输出。 – spencer7593

0

您可以将其作为聚合查询来完成。我喜欢这种方法,因为我觉得这是最灵活的定义一组中的元素:

select id 
from wp_posts p JOIN 
    wp_term_relationships t 
    ON t.object_id = p.ID 
group by id 
having sum(case when term_taxonomy_id = 80 then 1 else 0 end) > 0 and -- in 80 
     sum(case when term_taxonomy_id = 109 then 1 else 0 end) = 0  -- not in 109 
相关问题