2013-12-04 3 views
1

Рассмотрим следующий Postgresql таблицы базы данных:Как вы определяете среднее значение столбца в 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 подвели меня. Есть предположения?

ответ

1
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

С 4 книги:

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

+0

Я обновил таблицу, включив в нее 4-ю книгу. :) – Huuuze

+0

Вам не нужен подзапрос. Посмотрите на мой ответ. –

+0

Какой дурацкий способ создания данных в SQLFiddle! Вы можете использовать многозначное предложение VALUES, чтобы сделать это гораздо менее болезненно; см. http://sqlfiddle.com/#!15/9635d/1 –

1

Вам понадобится подзапрос. Внутренний запрос будет count книг с GROUP BY author; внешний запрос будет сканировать результаты внутреннего запроса и avg их.

Для этого можно использовать подзапрос в предложении FROM или вы можете использовать выражение CTE (WITH).

0

Должно работать:

SELECT AVG(cnt) FROM (
    SELECT COUNT(*) cnt FROM t 
    GROUP BY author_id 
) s 
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 строки, и я получил followng результатов:

  • Моего запрос с 2 DISTINCTS: ~ 70ms
  • Моего запрос с 1 DISTINCT: ~ 40ms
  • подход Мартина Бута: ~ 30ms

Затем добавляют 1 Milion строки и снова испытываться:

  • мой запрос с 2 DISTINCTS: ~ 1520ms
  • Мой запрос с 1 DISTINCT: ~ 820ms
  • подход Мартин Бут: ~ 1060ms

Затем добавили еще 9 Milion строки и испытаны снова:

  • Мой запрос с 2 DISTINCTS: ~ 17s
  • Мой запрос с 1 DISTINCT: ~ 11s
  • подход
  • Мартин Бут: ~ 19s

Таким образом, универсального решения нет.

+0

Интересный подход; он должен избегать узла HashAggregate подзапроса, но будет использовать несколько дорогие 'count (different)' на двух независимых ключах. Мне было бы интересно посмотреть, как эти два сравниваются по производительности с нетривиальным набором данных. –

+0

@CraigRinger: Вы правы. Я добавил результаты теста производительности к моему ответу. –

+0

Я не был уверен, на каком пути он пойдет. Кроме того, «возможно медленнее» не означает «неправильно». Спасибо, что попробовали. –

Смежные вопросы