我有两个表posts
和category_relationships
。我需要根据以下逻辑得出一些复杂的结果。
帖子表
id | post
-----|------------------------------|
1000 | Lorem ipsum dolor sit amet |
1001 | consectetur adipiscing elit |
1002 | sed do eiusmod tempor ut |
1004 | abore et dolore magna aliqua |
category_relationships表
post_id cat_id
---------|---------|
1000 | 201 |
1000 | 202 |
1000 | 211 |
1001 | 201 |
1001 | 211 |
1002 | 202 |
1002 | 212 |
首先,我将尝试解释我的类别结构。我有以下三个层次的结构。 (为简单起见,我这里不包括任何类别表)
flight [level 1] [ID : 100]
- class [level 2] [ID : 200]
-- economy [level 3] [ID : 201]
-- business [level 3] [ID : 202]
-- first [level 3] [ID : 203]
- alliance [level 2] [ID : 210]
-- star [level 3] [ID : 211]
-- oneworld [level 3] [ID : 212]
-- skyteam [level 3] [ID : 213]
现在使用算法:
我需要根据以下规则将所有帖子标记为flight
类别或任何子级。
我需要排除标记为economy
(ID:201)的帖子;
business
或first
)被标记了,它仍然应该出现在结果集中。alliance
也标记了economy
或其子项,则不应考虑这些帖子请注意,我可以根据结构获取类别ID,并在查询中使用它们。
到目前为止,我的方法:
SELECT posts.ID FROM posts
LEFT JOIN category_relationships AS tt1 ON (posts.ID = tt1.post_id)
WHERE tt1.cat_id IN (100,200,201,202,203,210,211,212,213)
AND posts.ID NOT IN ( SELECT post_id FROM category_relationships WHERE cat_id IN (201) )
但是这里的问题是它删除了所有标记为economy
的帖子。但是,它不满足规则编号1。
理想的结果集将像下面这样;
1000 - rule number 1
1002 - anyway no `economy` tagged
不包括:
1001 - rule number 2
1004 - no tagged
希望您对此问题有个清晰的主意,任何帮助都会非常感激。
答案 0 :(得分:1)
因此,您的条件之一是“它没有类别201或它具有类别202或203”。您缺少OR条件OR tt1.cat_id IN (202, 203)
:
SELECT DISTINCT posts.ID FROM posts
JOIN category_relationships AS tt1 ON (posts.ID = tt1.post_id)
WHERE tt1.cat_id IN (100,200,201,202,203,210,211,212,213)
AND (
posts.ID NOT IN ( SELECT post_id FROM category_relationships WHERE cat_id IN (201) )
OR
tt1.cat_id IN (202, 203)
)
请注意,您的LEFT JOIN没有意义,并且会被引擎转换为INNER JOIN。
但是-我将通过以下方式编写查询:
SELECT posts.ID
FROM posts
JOIN category_relationships AS tt1 ON posts.ID = tt1.post_id
WHERE tt1.cat_id IN (100,200,201,202,203,210,211,212,213)
GROUP BY posts.ID
HAVING SUM(tt1.cat_id = 201) = 0
OR SUM(tt1.cat_id = 202) > 0
OR SUM(tt1.cat_id = 203) > 0