Использование оконных функций может вам очень помочь: https://www.postgresql.org/docs/current/static/tutorial-window.html
demo: db <> fiddle
Мои данные испытаний:
isbn borrowed
9998-01-101-1 2018-08-01
9998-01-101-2 2018-08-01
9998-01-101-3 2018-08-01
9998-01-101-4 2018-08-01
9998-01-101-5 2018-08-01
9998-01-101-1 2018-08-02
9998-01-101-2 2018-08-02
9998-01-101-3 2018-08-02
9998-01-101-4 2018-08-03
9998-01-101-5 2018-08-03
9998-01-101-1 2018-08-04
9998-01-101-2 2018-08-04
9998-01-101-3 2018-08-04
9998-01-101-4 2018-08-04
9998-01-101-5 2018-08-05
9998-01-101-1 2018-08-05
Запрос:
SELECT
*
FROM (
SELECT
*,
borrowed_all_time::decimal / COUNT(*) OVER () as avg_borrows_per_day -- D
FROM (
SELECT DISTINCT -- C
borrowed,
COUNT(*) OVER (PARTITION BY borrowed) as borrowed_on_day, -- A
COUNT(*) OVER () as borrowed_all_time -- B
FROM book
)s
)s
WHERE borrowed_on_day > avg_borrows_per_day -- E
A: Эта оконная функция подсчитывает количество строк за borrowed
дату
B: Этооконная функция подсчитывает все строки, которые равны подсчетам заимствований за все время .
Результат пока выглядит следующим образом:
borrowed borrowed_on_day borrowed_all_time
2018-08-01 5 16
2018-08-01 5 16
2018-08-01 5 16
2018-08-01 5 16
2018-08-01 5 16
2018-08-02 3 16
2018-08-02 3 16
2018-08-02 3 16
2018-08-03 2 16
2018-08-03 2 16
2018-08-04 4 16
2018-08-04 4 16
2018-08-04 4 16
2018-08-04 4 16
2018-08-05 2 16
2018-08-05 2 16
C: потому что нам не нужны дубликатымы исключаем их с помощью DISTINCT
D: подсчет всех рядов после удаления всех связанных рядов дает счет различных дней.Это деление займов за все время дает средних займов в день .Приведение decimal
необходимо.Он преобразует целочисленное деление (16 / 5 == 3
) в деление с плавающей запятой (16 / 5 == 3.2
)
E: теперь мы можем отфильтровать заимствований за текущий день > средних заимствований за день .
Результат:
borrowed
2018-08-01
2018-08-04