从SQL表计算空关系
我试图统计那些在我们的系统中没有任何文章的作者,这会聚集网站上的作者。我有一个查询正在运行,但没有执行 到目前为止,我提出的最好的问题是:从SQL表计算空关系,sql,sqlite,postgresql,Sql,Sqlite,Postgresql,我试图统计那些在我们的系统中没有任何文章的作者,这会聚集网站上的作者。我有一个查询正在运行,但没有执行 到目前为止,我提出的最好的问题是: select count(*) as count_all from ( select authors.id from authors left outer join site_authors on site_authors.author_id = authors.id left outer join articles on articles.
select count(*) as count_all
from (
select authors.id
from authors
left outer join site_authors on site_authors.author_id = authors.id
left outer join articles on articles.site_author_id = site_authors.id
group by authors.id
having count(articles.id) = 0
) a;
但是,子查询效率相当低。我希望能有办法把它弄平。我有几个类似的查询,它们在左侧外部联接上添加了额外的条件,因此在我的模式中添加count列实际上不是一个选项
额外麻烦:这是一个跨平台查询,需要同时对pgSQL、SQLite和MySQL进行操作。您可以尝试稍微不同的查询,但我不确定它是否会更快:
select count(*)
from authors as a
where not exists (
select b.id
from site_authors as b
inner join
articles as c
on a.id=b.author_id and b.id=c.site_author_id)
当然,我认为您在表上有适当的索引:
- 站点作者:唯一(作者id,id)
- 文章:非唯一(站点\作者\ id)
Select count(*)
from authors
where id not in (select author_id from site_authors)
and id not in (select site_author_id from articles);
确保编者id和站点编者id已编入索引。优化器将注意到您正在执行的操作,并为“NOT IN”子句创建索引查找。假设“正常”联接更简单、更快,您可以从总作者数中减去有文章的作者数:
SELECT (SELECT COUNT(*)
FROM authors) -
(SELECT COUNT(DISTINCT site_authors.author_id)
FROM site_authors
JOIN articles ON articles.site_author_id = site_authors.id)
或者,尝试子查询:
SELECT COUNT(*)
FROM authors
WHERE id NOT IN (SELECT site_authors.author_id
FROM site_authors
JOIN articles ON articles.site_author_id = site_authors.id)
不会再慢了。(验证smomething不存在要比计算元组并将结果与零进行比较便宜)是的,PG显示它的速度是原来的两倍。原始查询的成本约为106,没有子计划。您的建议花费了214美元,还有一个子计划。@SEK这是建立索引和收集/重建STA的吗?是的。索引所有不起作用的外键。authors.id不是站点作者id的fk。它需要对站点作者/文章的内部联接执行子查询。然而,这可能更有效率。我来试试看这些数字是否有效。啊,是的。我没有注意到那是间接的。not in子句可以应用于select/join。现在我很好奇。让我知道,效率要低得多。PG没有把它作为索引,而不是在前者可能是个好主意,但这种方法对我的其他查询不起作用,比如在上个月没有发表任何文章的作者。第一种方法似乎很有希望,但取决于让它有效地使用索引联接。例如,站点作者比作者多得多,所以最好对作者进行内部连接,而不是进行区分。当我用这个额外的内部连接测试它时,它将成本从10k降到了112,只比我原来的查询多6倍。另一方面,我已经查询了完整计数,因此我可能能够对其进行调优,以便它在应用程序方面做更多的工作