我有一个带有类似
模式的postgres数据库CREATE TABLE authors (
id integer NOT NULL
);
CREATE TABLE posts (
id integer NOT NULL,
author_id integer,
text text
);
CREATE TABLE comments (
id integer NOT NULL,
post_id integer,
ordinal integer DEFAULT 0,
author_id integer
);
鉴于具体author_id
,我希望能够选择一批20个帖子:
我认为#1点正在扼杀我的查询时间。到目前为止,我使用内部查询来解决这一点,比如
SELECT * from posts
WHERE posts.id NOT IN (
SELECT posts.id FROM posts JOIN comments ON posts.id = comments.post_id)
随着我的数据库的增长,这个查询变得更糟。我不擅长SQL;有一个更好的方法吗?我正在使用ActiveRecord,如果这有助于/伤害。
答案 0 :(得分:0)
用这个替换你的查询
SELECT * from posts p, comments c
WHERE posts.id <> c.posts.id;
希望有所帮助
答案 1 :(得分:0)
我的经验是“不在”中查询时间比任何事情都要多。替代品“不存在”或者,如果postgresql支持这种语法。
where somefield in
(select somefield
from etc
except
select somefield
from etc)
有时使用减号这个词而不是除外。
答案 2 :(得分:0)
您提出的查询效率不必要。首先,您可以通过在子查询中省略冗余JOIN来简化:
SELECT *
FROM posts
WHERE posts.id NOT IN (SELECT post_id FROM comments)
这可以改写为LEFT JOIN / IS NULL
或NOT EXISTS
半反连接,我期望其表现最佳:
SELECT *
FROM posts p
WHERE NOT EXISTS (SELECT 1 FROM comments c WHERE c.post_id = p.id)
你的观点3.不清楚:
是否包括该帖子的10条最新评论。
忽略那个,查询可能是:
SELECT *
FROM posts p
WHERE p.author_id <> $author_id -- "not a post by that author"
AND NOT EXISTS (
SELECT 1
FROM comments c
WHERE c.author_id = $author_id
AND c.post_id = p.id) -- exclude "post that has a comment by that author"
-- ORDER BY ??undefined??, maybe id DESC
LIMIT 20
posts.author_id
应定义为NOT NULL
,否则您必须使用:
p.author_id IS DISTINCT FROM $author_id
对于大量行,索引是性能的关键。我希望posts.id
成为主键,因此它会自动编入索引。如果您还没有这个多列索引,请添加:
CREATE INDEX comments_pa_idx ON comments (post_id, author_id);