mySQL SELECT FROM table WHERE ... AND ... AND ... AND

时间:2011-11-09 12:09:30

标签: mysql sql select

我有一个包含列和数据的表“文章”:

article_id     title               body
1            This is the title   This is the body text
2            Another title       Another body text

另一个包含列和数据的表“类别”:

category_id    category
1              localnews
2              visible
3              first10

包含列和数据的表“类别”:

categories_id   article_id  category_id
1               1           1
2               1           2
3               1           3
4               2           1
5               2           3

我想选择行,其中categories.category_id = 1 AND = 2 AND = 3

我正在使用:

SELECT articles.article_id, articles.title, articles.body, 
categories.article_id, categories.category_id 
FROM articles, categories 
WHERE articles.article_id = categories.article_id 
AND categories.article_id = 1 
AND categories.article_id = 2 
AND categories.article_id = 3 

但它不起作用。显然mySQL需要另一种语法。 有人可以帮忙吗? 感谢

4 个答案:

答案 0 :(得分:3)

SELECT 
   Articles.article_id, 
   COUNT( Categories.article_id ) AS total 
FROM CategoryArticles 
LEFT JOIN Articles USING (article_id)
WHERE 
   CategoryArticles.category_id IN (1,2,3)
GROUP BY CategoryArticles.article_id
HAVING  total = 3

我在表格中使用了一些不同的名称,因为在您的示例中,categorycategories之间的区别很难被注意到。

答案 1 :(得分:1)

行的列不能同时为1,2或3 ,这是AND规定的内容。在OR条件下使用WHERE。更好 - 为了便于阅读 - 您可以使用IN

SELECT ...
WHERE `categories`.`article_id` IN(1,2,3)

答案 2 :(得分:1)

除了常用的IN()和使用HAVING计数之外,我还会对多重连接的性能差异感兴趣,如下所示......

SELECT STRAIGHT_JOIN
      articles.article_id, 
      articles.title, 
      articles.body
   FROM 
      categories c1
         JOIN articles
            on c1.article_id = articles.article_id
         JOIN categories c2
            on c1.article_id = c2.article_id
           AND c2.category_id = 2
         JOIN categories c3
            on c1.article_id = c3.article_id
           AND c3.category_id = 3
  WHERE
     c1.Category_ID = 1

是的,这可能看起来很模糊,但让我们考虑一下......通过在类别表上进行联接FIRST,其中您的一个特定类别 - 首先来自类别的实例应该代表具有哪个类别的类别最小的粒度。例如:您的本地新闻,可见和第一的类别10.本地新闻可能会拥有最多的条目,而Visible和First 10甚至更​​少......那些甚至会有最少数量的记录。使用此类别作为where子句。

所以,你说你有10万篇文章,其中90,000篇是本地新闻,45,000篇是Visible,12,000篇是第10篇。通过仅查看12,000篇文章,你就可以消除大部分数据。

然后加入文章表,并根据其他条件将AGAIN分类为别名C2和C3,如果找到,已完成,如果没有,则将其排除。

同样,我想知道性能影响。我也会在类别表上有一个复合索引(article_id,category_id)

答案 3 :(得分:0)

值不能同时为全部三个值,因此您最好使用IN中的WHERE子句来定义要返回的值。给你已经有一个连接条件,你也想把它移到ON子句中;即:

SELECT articles.article_id, articles.title, articles.body, categories.article_id, categories.category_id 
FROM articles
INNER JOIN categories ON articles.article_id = categories.article_id 
WHERE categories.article_id IN ( 1, 2, 3 )

当然,您可以进入下一步并执行:

SELECT articles.article_id, articles.title, articles.body, category.category
FROM articles
INNER JOIN categories ON articles.article_id = categories.article_id 
INNER JOIN category ON categories.category_id = category.category_id
WHERE categories.article_id IN ( 1, 2, 3 )

如果您只想展示出现在所有三个类别中的文章,那么您可以采取以下方法:

SELECT articles.article_id, articles.title, articles.body
FROM articles
INNER JOIN categories AS c1
ON articles.article_id = c1.article_id 
AND   c1.category_id = 1
INNER JOIN categories AS c2
ON articles.article_id = c2.article_id 
AND   c2.category_id = 2
INNER JOIN categories AS c3
ON articles.article_id = c3.article_id 
AND   c3.category_id = 3