Не так горжусь моим другим ответом
Просто используйте avg
.
Сегодня я узнал rows between unbounded preceding and current row
.И это работает с фактическим расположением данных даже при отсутствии хорошего поля кандидата на order by
.Похоже, что, по крайней мере, вы можете избежать использования скрытого поля Postgres ctid
, или вы можете даже избежать использования первичного последовательного интерфейса.Тем не менее, рекомендуется использовать серийный первичный ключ или поле для создания даты до order by
после.
Вот лучший запрос.Нет необходимости делить, просто используйте avg
select
id, value,
avg(value) over(arrangement rows between unbounded preceding and current row)
from tbl
window arrangement as (partition by id);
Выход
| id | value | avg |
|----|-------|--------------------|
| 1 | 2 | 2 |
| 1 | 4 | 3 |
| 1 | 3 | 3 |
| 2 | 1 | 1 |
| 2 | 2 | 1.5 |
| 2 | 5 | 2.6666666666666665 |
select
id, value,
sum(value) over(arrangement), rank() over(arrangement),
sum(value) over(arrangement)::numeric / rank() over(arrangement)
as relative_average,
avg(value) over(arrangement rows between unbounded preceding and current row)
from tbl
window arrangement as (partition by id order by id);
Выход:
| id | value | sum | rank | relative_average | avg |
|----|-------|-----|------|------------------|--------------------|
| 1 | 2 | 9 | 1 | 9 | 2 |
| 1 | 4 | 9 | 1 | 9 | 3 |
| 1 | 3 | 9 | 1 | 9 | 3 |
| 2 | 1 | 8 | 1 | 8 | 1 |
| 2 | 2 | 8 | 1 | 8 | 1.5 |
| 2 | 5 | 8 | 1 | 8 | 2.6666666666666665 |
select
id, value,
sum(value) over(arrangement), rank() over(arrangement),
sum(value) over(arrangement)::numeric / rank() over(arrangement)
as relative_average,
avg(value) over(arrangement rows between unbounded preceding and current row)
from tbl
window arrangement as (partition by id order by tbl.ctid);
Выход:
| id | value | sum | rank | relative_average | avg |
|----|-------|-----|------|--------------------|--------------------|
| 1 | 2 | 2 | 1 | 2 | 2 |
| 1 | 4 | 6 | 2 | 3 | 3 |
| 1 | 3 | 9 | 3 | 3 | 3 |
| 2 | 1 | 1 | 1 | 1 | 1 |
| 2 | 2 | 3 | 2 | 1.5 | 1.5 |
| 2 | 5 | 8 | 3 | 2.6666666666666665 | 2.6666666666666665 |
select
id, value,
sum(value) over(arrangement), rank() over(arrangement),
sum(value) over(arrangement)::numeric / rank() over(arrangement)
as relative_average,
avg(value) over(arrangement rows between unbounded preceding and current row)
from tbl
window arrangement as (partition by id order by ordered_pk);
Вывод:
| id | value | sum | rank | relative_average | avg |
|----|-------|-----|------|--------------------|--------------------|
| 1 | 2 | 2 | 1 | 2 | 2 |
| 1 | 4 | 6 | 2 | 3 | 3 |
| 1 | 3 | 9 | 3 | 3 | 3 |
| 2 | 1 | 1 | 1 | 1 | 1 |
| 2 | 2 | 3 | 2 | 1.5 | 1.5 |
| 2 | 5 | 8 | 3 | 2.6666666666666665 | 2.6666666666666665 |
Живой тест: http://sqlfiddle.com/#!17/f18276/9
rows between unbounded preceding and current row
также можно записать как rows unbounded preceding
http://sqlfiddle.com/#!17/f18276/11
И вот результат с order by value
, когда значение имеет дубликаты.
select
id, value,
sum(value) over(arrangement),
row_number() over(arrangement) as rn,
rank() over(arrangement) as rank,
dense_rank() over(arrangement) drank,
trunc( sum(value) over(arrangement)::numeric
/ row_number() over(arrangement), 2) as ra__rn,
trunc( sum(value) over(arrangement)::numeric
/ row_number() over(arrangement), 2) as ra__rank,
trunc( sum(value) over(arrangement)::numeric
/ row_number() over(arrangement), 2) as ra__drank,
trunc( avg(value) over(arrangement
rows between unbounded preceding and current row), 2) as ra
from tbl
window arrangement as (partition by id order by value)
Вывод:
| id | value | sum | rn | rank | drank | ra__rn | ra__rank | ra__drank | ra |
|----|-------|-----|----|------|-------|--------|----------|-----------|------|
| 1 | 2 | 2 | 1 | 1 | 1 | 2 | 2 | 2 | 2 |
| 1 | 3 | 5 | 2 | 2 | 2 | 2.5 | 2.5 | 2.5 | 2.5 |
| 1 | 4 | 9 | 3 | 3 | 3 | 3 | 3 | 3 | 3 |
| 2 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| 2 | 2 | 5 | 2 | 2 | 2 | 2.5 | 2.5 | 2.5 | 1.5 |
| 2 | 2 | 5 | 3 | 2 | 2 | 1.66 | 1.66 | 1.66 | 1.66 |
| 2 | 5 | 10 | 4 | 4 | 3 | 2.5 | 2.5 | 2.5 | 2.5 |
Живой тест: http://sqlfiddle.com/#!17/2b5aac/16
И вотрезультат с order by ordered_pk
, когда значение имеет дубликаты.
select
id, value,
sum(value) over(arrangement),
row_number() over(arrangement) as rn,
rank() over(arrangement) as rank,
dense_rank() over(arrangement) drank,
trunc( sum(value) over(arrangement)::numeric
/ row_number() over(arrangement), 2) as ra__rn,
trunc( sum(value) over(arrangement)::numeric
/ row_number() over(arrangement), 2) as ra__rank,
trunc( sum(value) over(arrangement)::numeric
/ row_number() over(arrangement), 2) as ra__drank,
trunc( avg(value) over(arrangement
rows between unbounded preceding and current row), 2) as ra
from tbl
window arrangement as (partition by id order by ordered_pk)
| id | value | sum | rn | rank | drank | ra__rn | ra__rank | ra__drank | ra |
|----|-------|-----|----|------|-------|--------|----------|-----------|------|
| 1 | 2 | 2 | 1 | 1 | 1 | 2 | 2 | 2 | 2 |
| 1 | 4 | 6 | 2 | 2 | 2 | 3 | 3 | 3 | 3 |
| 1 | 3 | 9 | 3 | 3 | 3 | 3 | 3 | 3 | 3 |
| 2 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| 2 | 2 | 3 | 2 | 2 | 2 | 1.5 | 1.5 | 1.5 | 1.5 |
| 2 | 2 | 5 | 3 | 3 | 3 | 1.66 | 1.66 | 1.66 | 1.66 |
| 2 | 5 | 10 | 4 | 4 | 4 | 2.5 | 2.5 | 2.5 | 2.5 |
Текущий тест: http://sqlfiddle.com/#!17/baaf9/2