MYSQL使用AND和OR条件查询同一列

MYSQL使用AND和OR条件查询同一列,mysql,relational-division,Mysql,Relational Division,我有以下表格: Topic Content_Topic Content id_topic topic id_content id_topic id_content content 1 aaaaa 1 2 1 xxxxx 2 bbbbb 1

我有以下表格:

       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_主题2,4,5或3,4,5或2,7,5或3,7,5等等。。。我收到了一个无效的结果

我做错了什么?

你说的是(2或3)和(4或7或10)和(5或9)

这意味着你永远不会得到任何结果

y = 2 or 3

x = 4, 7 or 10

z = 5 or 9
在那种情况下,不可能使
x和y
为真

我会使用表别名引用您的内容主题表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)
你说的是(2或3)和(4或7或10)和(5或9)

这意味着你永远不会得到任何结果

y = 2 or 3

x = 4, 7 or 10

z = 5 or 9
在那种情况下,不可能使
x和y
为真

我会使用表别名引用您的内容主题表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 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 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的所有
内容。您可以根据需要使用更多的
条件扩展
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的所有
内容。您可以根据需要使用更多的
条件扩展
HAVING
子句


另一件需要注意的事情是,您实际上不需要为该任务引入
主题
表(您想要的信息可以在
内容_主题
中找到)。

看起来您正在进行一种特殊类型的关系划分。也就是说,您正在查找与一组主题相匹配的内容,其中每个元素都有替换项

不能仅对
WHERE
子句中的条件执行此操作,因为该条件一次计算一行。给定的行上没有同时为2、4和5的
id\u 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)
此查询必须将内容与三个主题相匹配。如果它不匹配所有三个,那么查询将不会返回内容


但是这三种方法都有不同的选择。

看起来您正在进行一种特殊类型的关系划分。也就是说,您正在查找与一组主题相匹配的内容,其中每个元素都有替换项

不能仅对
WHERE
子句中的条件执行此操作,因为该条件一次计算一行。给定的行上没有同时为2、4和5的
id\u 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)
此查询必须将内容与三个主题相匹配。如果它不匹配所有三个,那么查询将不会返回内容


但是这三种方法都有替代方法。

如果这种方法不可行,您知道另一种管理方法吗?感谢您的帮助查看我的编辑,了解我认为您需要的内容-它未经测试,如果您想要一个工作示例,请安装SQLFIDLE并提供Content c中的链接
。。在=c、 id\u主题
您在哪里找到的?在
Content
表中没有
id\u主题
字段。这似乎有效,似乎是最好的解决方案。我做了一些更正和更改:ct1.id_content=c.id_topic到ct1.id_content=c.id_content,我添加了一个DISTINCT,因为有重复项。如果确定,并且您修改了您的答案,我接受它作为解决方案。选择DISTINCT(c.id\u content),c.*自ct1上的内容c内部连接内容c主题ct1。id\u content=c.id\u content和(ct1.id\u Topic=2或ct1.id\u Topic=3)内部连接内容c主题ct2。id\u content=c.id\u content=c.id\u content和(4,7,10)中的(ct2.id\u Topic)内部连接内容ct3。id\u content=c.id\u content和(ct3.id\u Topic=9)如果这种方法不可行,您知道另一种管理方法吗?感谢您的帮助查看我的编辑,了解我认为您需要的内容-它未经测试,如果您想要一个工作示例,请安装SQLFIDLE并提供Content c中的链接
。。在=c、 id\u主题
您在哪里找到的?在
Content
表中没有
id\u主题
字段。这似乎有效,似乎是最好的解决方案。我做了一些更正和更改:ct1.id_content=c.id_topic到ct1.id_content=c.id_content,我添加了一个DISTINCT,因为有重复项。如果确定,并且您修改了您的答案,我接受它作为解决方案。选择DISTINCT(c.id\u content),c.*自ct1上的内容c内部连接内容c主题ct1。id\u content=c.id\u content和(ct1.id\u Topic=2或ct1.id\u Topic=3)内部连接内容c主题ct2。id\u content=c.id\u content=c.id\u content和(4,7,10)中的(ct2.id\u Topic)内部连接内容ct3。id\u content=c.id\u content和(ct3.id\u Topic=9)使用联接而不是子选择:使用联接而不是子选择:使用联接而不是子选择:使用联接而不是子选择:此操作有效,但在