这是其中的一天,我无法解决这个问题。
我有以下查询:
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 2,因为ID 1同时是80和109。
我知道我已经完成了这一百万次,但我无法为我的生活做到这一点。有什么帮助吗?
答案 0 :(得分:2)
你可以写:
SELECT *
FROM wp_posts
JOIN wp_term_relationships
ON wp_term_relationships.object_id = wp_posts.ID
WHERE term_taxonomy_id = 80
AND wp_posts.id NOT IN
( SELECT object_id
FROM wp_term_relationships
WHERE term_taxonomy_id = 109
)
;
(见§ 13.2.10.3 "Subqueries with ANY
, IN
, or SOME
" in the MySQL 5.6 Reference Manual。)
答案 1 :(得分: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连接(别名为n
),以查找类别109
中的匹配行,但排除发现匹配的任何行(通过条件)在WHERE
子句中,所以从wp_posts返回的行是那些不属于类别109的行。
在SQL术语中,我们将此操作称为“反连接”。
注意:如果(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以查看执行计划,并测试一个是否比另一个“更快”。
还有其他方法。性能取决于可用(合适)索引,数据分布和生成的执行计划。
答案 2 :(得分: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