使用JOIN或WHERE查询(SELECT COUNT(*)...)> = 1?

时间:2017-10-05 08:11:37

标签: sql sqlite

我有一个包含大约20个表的数据库模式。为了我的问题,我只用3个表简化了询问:

* posts
    id
    title
    ...
* posts_users
    post_id
    user_id
    status (draft, published, etc)
    ...
* users
    id
    username
    ... 

出于本主题之外的原因,PostsUsers有多个"多对多"关系和状态字段是posts_users的一部分(可能位于posts表中)。

我想发布帖子。我在两种查询之间犹豫不决:

SELECT posts.*
FROM posts
INNER JOIN posts_users ON posts_users.post_id = posts.id
WHERE status = 'published'

SELECT posts.*
FROM posts
WHERE (
    SELECT COUNT(*)
    FROM posts_users
    WHERE post_id = posts.id
        AND status = 'published'
) >= 1

(我已经简化了我的问题,但实际上,帖子与更多其他数据相关联以进行过滤)

我的数据库是SQLite。我的问题是:

  1. 有什么区别?
  2. 哪种查询方式在性能方面最佳?

2 个答案:

答案 0 :(得分:2)

这些查询具有不同的语义:如果多个用户发布了帖子(如果可能的话),则第一个查询返回多行。

SQLite查询优化器通常不能重写,因此您编写的内容很可能就是它的实现方式。因此,您的第二个查询将计算所有posts_users条目,如果您只想知道是否至少有一个,则不需要这些条目。你应该更好地使用EXISTS。

编写第二个查询的更简单方法是:

SELECT *
FROM posts
WHERE id IN (SELECT post_id
             FROM posts_users
             WHERE status = 'published');

(这是SQLite将其重写为相关子查询的一种情况,如果它估计它更有效。)

最终,所有这些查询都必须查找相同的行并具有相似的性能;最重要的是你有适当的索引。 (但在这种情况下,如果发布大多数帖子,status上的索引就无济于事。)

答案 1 :(得分:0)

我可以告诉你这个查询的性能取决于你的行和列表。

在查询1 - 加入是

  

Output.row = tableA.row * tableB.row

     

Output.column = tableA.column * tableB.column

在查询2中 - 选择这样的计数:

  

Output.row = tableA.row + tableB.row

     

Output.column = tableA.column + tableB.column

我建议使用查询2来获得更多性能。