Mysql 根据给定结构的复杂SQL连接查询
我有两个表Mysql 根据给定结构的复杂SQL连接查询,mysql,sql,database,jointable,Mysql,Sql,Database,Jointable,我有两个表posts和category\u关系。我需要根据下面的逻辑得到一些复杂的结果 帖子表 id | post -----|------------------------------| 1000 | Lorem ipsum dolor sit amet | 1001 | consectetur adipiscing elit | 1002 | sed do eiusmod tempor ut | 1004 | abore et dolore magna
posts
和category\u关系
。我需要根据下面的逻辑得到一些复杂的结果
帖子表
id | post
-----|------------------------------|
1000 | Lorem ipsum dolor sit amet |
1001 | consectetur adipiscing elit |
1002 | sed do eiusmod tempor ut |
1004 | abore et dolore magna aliqua |
post_id cat_id
---------|---------|
1000 | 201 |
1000 | 202 |
1000 | 211 |
1001 | 201 |
1001 | 211 |
1002 | 202 |
1002 | 212 |
类别关系表
id | post
-----|------------------------------|
1000 | Lorem ipsum dolor sit amet |
1001 | consectetur adipiscing elit |
1002 | sed do eiusmod tempor ut |
1004 | abore et dolore magna aliqua |
post_id cat_id
---------|---------|
1000 | 201 |
1000 | 202 |
1000 | 211 |
1001 | 201 |
1001 | 211 |
1002 | 202 |
1002 | 212 |
首先,我将尝试解释我的类别结构。我有三层结构,如下所示。(为了简单起见,我这里不包括任何类别表)
现在算法:
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) )
我需要根据以下规则将所有帖子标记为flight
category或任何child/child
我需要排除标记为经济
(ID:201)的帖子
business
或first
)被标记,则它仍应在结果集中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
希望您对这个问题有清晰的认识,任何帮助都将不胜感激。将您的条件从where子句移至ON子句
SELECT posts.ID FROM posts
LEFT JOIN category_relationships AS tt1 ON (posts.ID = tt1.post_id)
and 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) )
将条件从where子句移动到ON子句
SELECT posts.ID FROM posts
LEFT JOIN category_relationships AS tt1 ON (posts.ID = tt1.post_id)
and 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) )
因此,您的条件之一是“它没有类别201,或者它有类别202或203”。您在(202,203)中缺少该或条件
或tt1.cat\u id:
请注意,您的左连接没有意义,将由引擎转换为内部连接
但是-我将按以下方式编写查询:
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
因此,您的条件之一是“它没有类别201,或者它有类别202或203”。您在(202,203)
中缺少该或条件或tt1.cat\u id:
请注意,您的左连接没有意义,将由引擎转换为内部连接
但是-我将按以下方式编写查询:
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
这是一个很好的候选分组方式
和具有
:
SELECT cr.post_id
FROM category_relationships cr
GROUP BY cr.post_id
HAVING SUM(cr.tag_id = 100) > 0 AND -- flight
(SUM(cr.tag_id = 201) > 0 OR -- economy
SUM(cr.tag_id IN (202, 203)) > 0 -- business/first
) AND
NOT (SUM(cr.tag_id = 201) > 0 OR -- economy
SUM(cr.tag_id IN (210, 211, 212, 213) = 0 -- alliance
);
这可能更容易使用标志:
SELECT cr.post_id
FROM (SELECT cr.*,
(cr.tag_id = 100) as is_flight,
(cr.tag_id = 201) as is_economy,
(cr.tag_id in (202, 203)) as is_first_business,
(cr.tag_id IN (210, 211, 212, 213)) as is_alliance
FROM category_relationships cr
) cr
GROUP BY cr.post_id
HAVING SUM(is_flight) > 0 AND
(SUM(is_economy) > 0 OR
SUM(is_business_first) > 0
) AND
NOT (SUM(is_economy) > 0 OR
SUM(is_alliance) > 0
);
这是一个很好的候选分组方式
和具有
:
SELECT cr.post_id
FROM category_relationships cr
GROUP BY cr.post_id
HAVING SUM(cr.tag_id = 100) > 0 AND -- flight
(SUM(cr.tag_id = 201) > 0 OR -- economy
SUM(cr.tag_id IN (202, 203)) > 0 -- business/first
) AND
NOT (SUM(cr.tag_id = 201) > 0 OR -- economy
SUM(cr.tag_id IN (210, 211, 212, 213) = 0 -- alliance
);
这可能更容易使用标志:
SELECT cr.post_id
FROM (SELECT cr.*,
(cr.tag_id = 100) as is_flight,
(cr.tag_id = 201) as is_economy,
(cr.tag_id in (202, 203)) as is_first_business,
(cr.tag_id IN (210, 211, 212, 213)) as is_alliance
FROM category_relationships cr
) cr
GROUP BY cr.post_id
HAVING SUM(is_flight) > 0 AND
(SUM(is_economy) > 0 OR
SUM(is_business_first) > 0
) AND
NOT (SUM(is_economy) > 0 OR
SUM(is_alliance) > 0
);
“问题是它正在删除所有标记为经济的帖子”-为什么这是一个问题?这是一个要求——“我需要排除标记为经济(ID:201)的帖子”@PaulSpiegel很抱歉混淆,实际上根据上面的一行,它应该满足我在正文中提到的两条规则。我明白了。。但这并不明显,“问题是它正在删除所有被贴上经济标签的帖子”-为什么这是一个问题?这是一个要求——“我需要排除标记为经济(ID:201)的帖子”@PaulSpiegel很抱歉混淆,实际上根据上面的一行,它应该满足我在正文中提到的两条规则。我明白了。。但这并不明显。@janitgchinthana你的开场白是矛盾的,所以我们不能know@janitgchinthana你的开场白是矛盾的,所以我们不知道或者说条件是有意义的,我想这就是我想要的。或者说条件是有意义的,我想这就是我想要的。