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)

此查询必须将一个内容与三个主题相匹配。如果三者都不匹配,则查询不会返回该内容。

但三者各有替补。