Оконные функции начинают вести себя интересно, если внутрь OVER
добавить ORDER BY
.
Посмотри внимательно на столбцы count_current
и count_total
в результате запроса:
SELECT pi.purchase_id,
pi.purchase_item_id,
pi.count AS count_item,
sum(pi.count) over (ORDER BY pi.purchase_id, pi.purchase_item_id) AS count_current,
sum(pi.count) over () AS count_total
FROM purchase_item pi
ORDER BY pi.purchase_id,
pi.purchase_item_id
# | purchase_id | purchase_item_id | count_item | count_current | count_total |
---|---|---|---|---|---|
1 | 1 | 1 | 1 | 1 | 54 |
2 | 1 | 2 | 30 | 31 | 54 |
3 | 2 | 3 | 1 | 32 | 54 |
4 | 3 | 4 | 1 | 33 | 54 |
5 | 3 | 5 | 1 | 34 | 54 |
6 | 4 | 6 | 2 | 36 | 54 |
7 | 5 | 7 | 1 | 37 | 54 |
8 | 6 | 8 | 1 | 38 | 54 |
9 | 6 | 9 | 1 | 39 | 54 |
10 | 6 | 10 | 1 | 40 | 54 |
11 | 7 | 11 | 3 | 43 | 54 |
12 | 8 | 12 | 1 | 44 | 54 |
13 | 9 | 13 | 1 | 45 | 54 |
14 | 10 | 14 | 5 | 50 | 54 |
15 | 10 | 15 | 1 | 51 | 54 |
16 | 10 | 16 | 1 | 52 | 54 |
17 | 11 | 17 | 1 | 53 | 54 |
18 | 11 | 18 | 1 | 54 | 54 |
С sum(pi.count) over () AS count_total
все понятно. Так как в over
ничего не указано, то sum
вычисляется по всем строкам.
Но если внутри over
написать ORDER BY
, то функция будет вычисляться не по всем строкам, а от первой строки и до текущей, включительно (не совсем так конечно, но об этом в следующих заданиях).
Чтобы вычислить агрегатную функцию по окну с указанием ORDER BY
внутри over
, делай так:
- Разбивай все строки результата на группы в соответствии с
PARTITION BY
, указанным вover
. В нашем случаеPARTITION BY
опущен, поэтому группа у нас одна - все строки. - Сортируй строки в группах в порядке, указанном в
ORDER BY
внутриover
. - Вычисляй функцию последовательно для строк, начиная с первой. Для каждой очередной строки для вычисления значения бери строки от начала и до текущей.
Для наглядности у результате у нас строки отсортированы в том же порядке, что и при вычислении оконной функции.
Для первой строки берем одну единственную строку
# | purchase_id | purchase_item_id | count_item | count_current | count_total |
---|---|---|---|---|---|
1 | 1 | 1 | 1 | 1 | 54 |
Для второй:
# | purchase_id | purchase_item_id | count_item | count_current | count_total |
---|---|---|---|---|---|
1 | 1 | 1 | 1 | 1 | 54 |
2 | 1 | 2 | 30 | 31 | 54 |
31 = 1 + 30
Для третьей:
# | purchase_id | purchase_item_id | count_item | count_current | count_total |
---|---|---|---|---|---|
1 | 1 | 1 | 1 | 1 | 54 |
2 | 1 | 2 | 30 | 31 | 54 |
3 | 2 | 3 | 1 | 32 | 54 |
32 = 1 + 30 + 1
И так далее...
С ORDER BY
себя так ведут все агрегатные оконные функции, не только sum
.