如何确定Postgresql中列的平均总数?

时间:2013-12-04 23:01:26

标签: sql postgresql count average

考虑以下Postgresql数据库表:

 id | book_id | author_id
---------------------------
 1  |    1    |    1
 2  |    2    |    1
 3  |    3    |    2
 4  |    4    |    2
 5  |    5    |    2
 6  |    6    |    3
 7  |    7    |    2

在这个例子中,作者1写了2本书,作者2写了4本书,作者3写了1本书。如何确定作者使用SQL编写的平均书籍数量?换句话说,我试图得到,“一位作家平均写了2.3本书。”

到目前为止,AVG和COUNT的尝试都让我失望。有什么想法吗?

4 个答案:

答案 0 :(得分:2)

select avg(totalbooks) from 
(select count(1) totalbooks from books group by author_id) bookcount

我认为你的示例数据实际上只有3本作者身份2的书,所以这不会返回2.3

http://sqlfiddle.com/#!15/3e36e/1

第四本书:

http://sqlfiddle.com/#!15/67eac/1

答案 1 :(得分:1)

你需要一个子查询。内部查询将count书籍GROUP BY author;外部查询将扫描内部查询的结果并avg它们。

您可以在FROM子句中使用子查询,也可以使用CTE(WITH表达式)。

答案 2 :(得分:1)

对于每位作者的平均书籍数量,您只需:

SELECT 1.0*COUNT(DISTINCT book_id)/count(DISTINCT author_id) FROM tbl; 

每位作者的书籍数量:

SELECT 1.0*COUNT(DISTINCT book_id)/count(DISTINCT author_id) 
FROM tbl GROUP BY author_id;

我们需要1.0因子才能使结果不是整数。

你可以根据你想要的结果删除DISTINCT(只有当一本书有很多作者时才重要。)

正如克雷格林格正确地指出的那样,2个区别可能很昂贵。为了测试性能,我已经生成了50 000行,并得到了以下结果:

  • 我的查询有2个DISTINCTS:~70ms
  • 我的查询1 DISTINCT:~40ms
  • Martin Booth的方法:~30ms

然后添加1百万行并再次测试:

  • 我的查询有2个DISTINCTS:~1520ms
  • 我的查询1 DISTINCT:~820ms
  • Martin Booth的方法:~1060ms

然后又添加了9百万行并再次测试:

  • 我的查询有2个DISTINCTS:~17s
  • 我的查询1 DISTINCT:~11s
  • Martin Booth的方法:〜19s

所以没有通用的解决方案。

答案 3 :(得分:0)

这应该有效:

SELECT AVG(cnt) FROM (
  SELECT COUNT(*) cnt FROM t
  GROUP BY author_id
) s