我有一个包含大约20个表的数据库模式。为了我的问题,我只用3个表简化了询问:
* posts
id
title
...
* posts_users
post_id
user_id
status (draft, published, etc)
...
* users
id
username
...
出于本主题之外的原因,Posts
和Users
有多个"多对多"关系和状态字段是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。我的问题是:
答案 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来获得更多性能。