MYSQL 使用 AND 和 OR 条件查询同一列
MYSQL Query same column with AND and OR conditions
我有以下表格:
Topic Content_Topic Content
id_topic topic id_content id_topic id_content content
1 aaaaa 1 2 1 xxxxx
2 bbbbb 1 4 2 yyyyy
3 ccccc 1 5 3 zzzzz
4 ddddd 2 1 4 wwwww
5 eeeee 2 3 5 kkkkk
6 fffff 2 5 6 jjjjj
... 3 3 ...
3 4
3 5
...
我正在尝试 运行 以下查询,但没有获得我期望的结果:
SELECT content FROM Content_Topic ct
LEFT JOIN Content c ON ct.id_content=c.id_topic
LEFT JOIN Topic t ON ct.id_topic=t.id_topic
WHERE (ct.id_topic=2 OR ct.id_topic=3) AND
ct.id_topic IN (4,7,10) AND
(ct.id_topic=5 OR ct.id_topic=9)
我希望所有内容都具有 id_topic 2,4,5 或 3,4,5 或 2,7,5 或 3,7,5 等等......我收到无效结果。
我做错了什么?
你说的是 (2 or 3) AND (4 or 7 or 10) AND (5 or 9)
这意味着你永远不会得到任何结果。
y = 2 or 3
x = 4, 7 or 10
z = 5 or 9
在那种情况下不可能使 x AND y
为真。
我会使用 table 别名来引用你的 Content_Topic table 3 次,这样你就可以使你的每个条件都有效,我会使用连接而不是子选择,因为它是更快:
SELECT content FROM Content c
INNER JOIN Content_Topic ct1 ON ct1.id_content=c.id_topic AND (ct1.id_topic=2 OR ct1.id_topic=3)
INNER JOIN Content_Topic ct2 ON ct2.id_content=c.id_topic AND (ct2.id_topic IN (4,7,10))
INNER JOIN Content_Topic ct3 ON ct3.id_content=c.id_topic AND (ct3.id_topic=5 OR ct3.id_topic=9)
我觉得你的加盟条件不对-
SELECT content
FROM Content_Topic ct
LEFT JOIN Content c ON ct.id_content=c.id_content
WHERE EXISTS (SELECT 1
FROM Topic T
WHERE T.id_topic = ct.Content_Topic
AND ct.id_topic IN (2, 3))
AND EXISTS (SELECT 1
FROM Topic T1
WHERE T1.id_topic = ct.Content_Topic
AND ct.id_topic IN (4,7,10))
AND EXISTS (SELECT 1
FROM Topic T2
WHERE T2.id_topic = ct.Content_Topic
AND ct.id_topic IN (5, 9))
SELECT *
FROM Content_Topic ct1
JOIN Content c1 ON ct`.id_content=c`.id_topic
JOIN ( SELECT id_content
FROM Content_Topic ct
LEFT JOIN Content c ON ct.id_content=c.id_topic
LEFT JOIN Topic t ON ct.id_topic=t.id_topic
GROUP BY id_content
HAVING SUM(ct.id_topic IN (2,3)) > 0
AND SUM(ct.id_topic IN (4,7,10)) > 0
AND SUM(ct.id_topic IN (5,9)) > 0
) sq ON ct.id_content = ct1.id_content
我认为使用聚合和用于过滤的 HAVING
子句可以更容易地完成此操作:
SELECT c.content
FROM Content c
INNER JOIN Content_Topic ct ON ct.id_content = c.id_content
GROUP BY c.id_content, c.content
HAVING
-- 2, 4, 5
(MAX(c.id_topic = 2) = 1 AND MAX(c.id_topic = 4) = 1 AND MAX(c.id_topic = 5) = 1)
-- 3, 4, 5
OR (MAX(c.id_topic = 3) = 1 AND MAX(c.id_topic = 4) = 1 AND MAX(c.id_topic = 5) = 1)
-- 2, 5, 7
OR (MAX(c.id_topic = 2) = 1 AND MAX(c.id_topic = 5) = 1 AND MAX(c.id_topic = 7) = 1)
-- add more if needed ...
这将为您提供具有主题 2、3 和 5,或主题 3、4 和 5,或主题 2、5 和 7 的所有 content
。您可以扩展 HAVING
子句根据需要添加更多 OR
条件。
另一件需要注意的事情是,您实际上不需要为该任务引入 Topic
table(您想要的信息在 Content_Topic
中可用)。
看起来你在做一种特殊类型的关系除法。也就是说,您正在寻找与一组主题相匹配的内容,其中每个元素都有替代项。
您不能只对 WHERE
子句中的条件执行此操作,因为一次针对一行评估该条件。给定行上没有同时为 2 和 4 和 5 的值 id_topic
。
您需要行集的条件,这就是关系划分。
对于您的情况,我会使用联接来完成。通过使用联接,您可以对 Content_Topic 的 不同 行进行三个引用,因此条件可以互斥。
SELECT c.content
FROM Content c
INNER JOIN Content_Topic ct1
ON c.id_content=ct1.id_content AND ct1.id_topic IN (2,3)
INNER JOIN Content_Topic ct2
ON c.id_content=ct2.id_content AND ct2.id_topic IN (4,7,10)
INNER JOIN Content_Topic ct3
ON c.id_content=ct3.id_content AND ct3.id_topic IN (5,9)
此查询必须将一个内容与三个主题相匹配。如果三者都不匹配,则查询不会返回该内容。
但三者各有替补。
我有以下表格:
Topic Content_Topic Content
id_topic topic id_content id_topic id_content content
1 aaaaa 1 2 1 xxxxx
2 bbbbb 1 4 2 yyyyy
3 ccccc 1 5 3 zzzzz
4 ddddd 2 1 4 wwwww
5 eeeee 2 3 5 kkkkk
6 fffff 2 5 6 jjjjj
... 3 3 ...
3 4
3 5
...
我正在尝试 运行 以下查询,但没有获得我期望的结果:
SELECT content FROM Content_Topic ct
LEFT JOIN Content c ON ct.id_content=c.id_topic
LEFT JOIN Topic t ON ct.id_topic=t.id_topic
WHERE (ct.id_topic=2 OR ct.id_topic=3) AND
ct.id_topic IN (4,7,10) AND
(ct.id_topic=5 OR ct.id_topic=9)
我希望所有内容都具有 id_topic 2,4,5 或 3,4,5 或 2,7,5 或 3,7,5 等等......我收到无效结果。
我做错了什么?
你说的是 (2 or 3) AND (4 or 7 or 10) AND (5 or 9)
这意味着你永远不会得到任何结果。
y = 2 or 3
x = 4, 7 or 10
z = 5 or 9
在那种情况下不可能使 x AND y
为真。
我会使用 table 别名来引用你的 Content_Topic table 3 次,这样你就可以使你的每个条件都有效,我会使用连接而不是子选择,因为它是更快:
SELECT content FROM Content c
INNER JOIN Content_Topic ct1 ON ct1.id_content=c.id_topic AND (ct1.id_topic=2 OR ct1.id_topic=3)
INNER JOIN Content_Topic ct2 ON ct2.id_content=c.id_topic AND (ct2.id_topic IN (4,7,10))
INNER JOIN Content_Topic ct3 ON ct3.id_content=c.id_topic AND (ct3.id_topic=5 OR ct3.id_topic=9)
我觉得你的加盟条件不对-
SELECT content
FROM Content_Topic ct
LEFT JOIN Content c ON ct.id_content=c.id_content
WHERE EXISTS (SELECT 1
FROM Topic T
WHERE T.id_topic = ct.Content_Topic
AND ct.id_topic IN (2, 3))
AND EXISTS (SELECT 1
FROM Topic T1
WHERE T1.id_topic = ct.Content_Topic
AND ct.id_topic IN (4,7,10))
AND EXISTS (SELECT 1
FROM Topic T2
WHERE T2.id_topic = ct.Content_Topic
AND ct.id_topic IN (5, 9))
SELECT *
FROM Content_Topic ct1
JOIN Content c1 ON ct`.id_content=c`.id_topic
JOIN ( SELECT id_content
FROM Content_Topic ct
LEFT JOIN Content c ON ct.id_content=c.id_topic
LEFT JOIN Topic t ON ct.id_topic=t.id_topic
GROUP BY id_content
HAVING SUM(ct.id_topic IN (2,3)) > 0
AND SUM(ct.id_topic IN (4,7,10)) > 0
AND SUM(ct.id_topic IN (5,9)) > 0
) sq ON ct.id_content = ct1.id_content
我认为使用聚合和用于过滤的 HAVING
子句可以更容易地完成此操作:
SELECT c.content
FROM Content c
INNER JOIN Content_Topic ct ON ct.id_content = c.id_content
GROUP BY c.id_content, c.content
HAVING
-- 2, 4, 5
(MAX(c.id_topic = 2) = 1 AND MAX(c.id_topic = 4) = 1 AND MAX(c.id_topic = 5) = 1)
-- 3, 4, 5
OR (MAX(c.id_topic = 3) = 1 AND MAX(c.id_topic = 4) = 1 AND MAX(c.id_topic = 5) = 1)
-- 2, 5, 7
OR (MAX(c.id_topic = 2) = 1 AND MAX(c.id_topic = 5) = 1 AND MAX(c.id_topic = 7) = 1)
-- add more if needed ...
这将为您提供具有主题 2、3 和 5,或主题 3、4 和 5,或主题 2、5 和 7 的所有 content
。您可以扩展 HAVING
子句根据需要添加更多 OR
条件。
另一件需要注意的事情是,您实际上不需要为该任务引入 Topic
table(您想要的信息在 Content_Topic
中可用)。
看起来你在做一种特殊类型的关系除法。也就是说,您正在寻找与一组主题相匹配的内容,其中每个元素都有替代项。
您不能只对 WHERE
子句中的条件执行此操作,因为一次针对一行评估该条件。给定行上没有同时为 2 和 4 和 5 的值 id_topic
。
您需要行集的条件,这就是关系划分。
对于您的情况,我会使用联接来完成。通过使用联接,您可以对 Content_Topic 的 不同 行进行三个引用,因此条件可以互斥。
SELECT c.content
FROM Content c
INNER JOIN Content_Topic ct1
ON c.id_content=ct1.id_content AND ct1.id_topic IN (2,3)
INNER JOIN Content_Topic ct2
ON c.id_content=ct2.id_content AND ct2.id_topic IN (4,7,10)
INNER JOIN Content_Topic ct3
ON c.id_content=ct3.id_content AND ct3.id_topic IN (5,9)
此查询必须将一个内容与三个主题相匹配。如果三者都不匹配,则查询不会返回该内容。
但三者各有替补。