Setiap window function membawa pertanyaan tersembunyi yang sampai sekarang kita biarkan PostgreSQL jawab sendiri: dari sekian baris di dalam partisi, sebagian mana yang ikut dihitung untuk baris ini? Jawaban itu ditentukan oleh window frame — himpunan baris yang berada dalam jangkauan fungsi pada saat memproses satu baris hasil. Selama ini kita menulis OVER (ORDER BY bulan) dan mendapat akumulasi berjalan tanpa pernah menyebut kata frame, karena PostgreSQL memilihkan frame default. Default itu tepat untuk running total, tetapi rata-rata bergerak di chapter sebelumnya sudah memaksa kita menulis ROWS BETWEEN 2 PRECEDING AND CURRENT ROW secara eksplisit. Chapter ini adalah bab konseptualnya: kita bedah aturan frame default, perbedaan mendasar antara mode ROWS dan RANGE — termasuk perilakunya saat nilai urut kembar — sintaks lengkap spesifikasi frame, dan opsi EXCLUDE yang membuang bagian tertentu dari frame.
Tabel Latihan #
Data latihan sengaja dirancang mengandung nilai kembar: setiap bulan diisi tiga baris — satu per produk — sehingga kolom bulan berulang tiga kali. Baris-baris dengan nilai urut yang sama ini disebut peer, dan peer-lah yang membuat perbedaan ROWS vs RANGE menjadi terlihat:
-- tabel latihan: pendapatan bulanan per produk, Januari-April 2026
-- kolom bulan sengaja memuat nilai kembar: tiga produk per bulan yang sama
CREATE TABLE penjualan_bulanan (
id integer PRIMARY KEY,
produk text NOT NULL,
bulan date NOT NULL,
pendapatan numeric(12,2) NOT NULL
);
INSERT INTO penjualan_bulanan (id, produk, bulan, pendapatan) VALUES
( 1, 'Gula Pasir', DATE '2026-01-01', 3200000.00),
( 2, 'Kopi Gayo', DATE '2026-01-01', 9200000.00),
( 3, 'Teh Melati', DATE '2026-01-01', 4100000.00),
( 4, 'Gula Pasir', DATE '2026-02-01', 3600000.00),
( 5, 'Kopi Gayo', DATE '2026-02-01', 9800000.00),
( 6, 'Teh Melati', DATE '2026-02-01', 4300000.00),
( 7, 'Gula Pasir', DATE '2026-03-01', 3100000.00),
( 8, 'Kopi Gayo', DATE '2026-03-01', 8900000.00),
( 9, 'Teh Melati', DATE '2026-03-01', 4600000.00),
(10, 'Gula Pasir', DATE '2026-04-01', 3800000.00),
(11, 'Kopi Gayo', DATE '2026-04-01', 10200000.00),
(12, 'Teh Melati', DATE '2026-04-01', 4400000.00);
SELECT id, produk, bulan, pendapatan
FROM penjualan_bulanan
ORDER BY bulan, produk;Output yang Dihasilkan:
CREATE TABLE
INSERT 0 12
id | produk | bulan | pendapatan
----+------------+------------+-------------
1 | Gula Pasir | 2026-01-01 | 3200000.00
2 | Kopi Gayo | 2026-01-01 | 9200000.00
3 | Teh Melati | 2026-01-01 | 4100000.00
4 | Gula Pasir | 2026-02-01 | 3600000.00
5 | Kopi Gayo | 2026-02-01 | 9800000.00
6 | Teh Melati | 2026-02-01 | 4300000.00
7 | Gula Pasir | 2026-03-01 | 3100000.00
8 | Kopi Gayo | 2026-03-01 | 8900000.00
9 | Teh Melati | 2026-03-01 | 4600000.00
10 | Gula Pasir | 2026-04-01 | 3800000.00
11 | Kopi Gayo | 2026-04-01 | 10200000.00
12 | Teh Melati | 2026-04-01 | 4400000.00
(12 rows)Frame Default yang Dipilih Diam-Diam #
Aturan frame default hanya ada dua dan keduanya ditentukan oleh ada-tidaknya ORDER BY di dalam OVER:
Kondisi OVER | Frame default |
|---|---|
Tanpa ORDER BY, tanpa frame | seluruh partisi |
Ada ORDER BY, tanpa frame | RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW |
Query berikut menampilkan tiga jendela berbeda dalam satu daftar SELECT sehingga ketiganya bisa dibandingkan baris demi baris:
-- frame default: tanpa ORDER BY, dengan ORDER BY, dan eksplisit ROWS
SELECT bulan,
produk,
pendapatan,
sum(pendapatan) OVER () AS total_semua,
sum(pendapatan) OVER (ORDER BY bulan) AS kumulatif_default,
sum(pendapatan) OVER (ORDER BY bulan, produk
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS baris_demi_baris
FROM penjualan_bulanan
ORDER BY bulan, produk;Output yang Dihasilkan:
bulan | produk | pendapatan | total_semua | kumulatif_default | baris_demi_baris
------------+------------+-------------+-------------+-------------------+------------------
2026-01-01 | Gula Pasir | 3200000.00 | 69200000.00 | 16500000.00 | 3200000.00
2026-01-01 | Kopi Gayo | 9200000.00 | 69200000.00 | 16500000.00 | 12400000.00
2026-01-01 | Teh Melati | 4100000.00 | 69200000.00 | 16500000.00 | 16500000.00
2026-02-01 | Gula Pasir | 3600000.00 | 69200000.00 | 34200000.00 | 20100000.00
2026-02-01 | Kopi Gayo | 9800000.00 | 69200000.00 | 34200000.00 | 29900000.00
2026-02-01 | Teh Melati | 4300000.00 | 69200000.00 | 34200000.00 | 34200000.00
2026-03-01 | Gula Pasir | 3100000.00 | 69200000.00 | 50800000.00 | 37300000.00
2026-03-01 | Kopi Gayo | 8900000.00 | 69200000.00 | 50800000.00 | 46200000.00
2026-03-01 | Teh Melati | 4600000.00 | 69200000.00 | 50800000.00 | 50800000.00
2026-04-01 | Gula Pasir | 3800000.00 | 69200000.00 | 69200000.00 | 54600000.00
2026-04-01 | Kopi Gayo | 10200000.00 | 69200000.00 | 69200000.00 | 64800000.00
2026-04-01 | Teh Melati | 4400000.00 | 69200000.00 | 69200000.00 | 69200000.00
(12 rows)Baca ketiga kolom hasilnya untuk baris Kopi Gayo bulan Februari. Kolom total_semua bernilai 69.200.000 — sama untuk seluruh dua belas baris, karena OVER () tanpa ORDER BY membuat frame-nya meliputi seluruh partisi (di sini: seluruh tabel). Kolom kumulatif_default bernilai 34.200.000 — dan inilah bagian yang penting: ketiga baris Februari menerima nilai yang sama, sebab frame default berupa RANGE, dan mode RANGE memotong frame berdasarkan nilai, bukan posisi baris. Frame baris Februasi berhenti di “akhir nilai Februari”, sehingga seluruh peer Februari masuk — kolom itu benar-benar berisi total Januari ditambah total Februari utuh. Kolom baris_demi_baris baru menampilkan akumulasi fisik baris per baris (20.100.000, 29.900.000, 34.200.000 untuk ketiga baris Februari) karena jendelanya menambahkan produk sebagai pemecah urut lalu memakai mode ROWS secara eksplisit.
ROWS vs RANGE: Posisi Fisik atau Kelompok Nilai #
Mode ROWS dan RANGE sama-sama menerima spesifikasi batas, tetapi menafsirkannya secara berbeda: ROWS menghitung posisi fisik baris dalam urutan partisi, sedangkan RANGE menghitung jarak nilai pada kolom urut — dan semua peer dianggap satu titik nilai yang sama. Query berikut membandingkan keduanya dengan batas 1 PRECEDING pada data bulan kembar. Karena dua jendela dipakai bergantian di query yang sama, definisinya diberi nama lewat klausa WINDOW agar tidak menumpuk di daftar SELECT:
-- ROWS vs RANGE pada data dengan bulan kembar: posisi fisik atau kelompok nilai
SELECT bulan,
produk,
pendapatan,
sum(pendapatan) OVER w_rows AS total_rows,
sum(pendapatan) OVER w_range AS total_range
FROM penjualan_bulanan
WINDOW w_rows AS (ORDER BY bulan ROWS BETWEEN 1 PRECEDING AND CURRENT ROW),
w_range AS (ORDER BY bulan RANGE BETWEEN INTERVAL '1 day' PRECEDING AND CURRENT ROW)
ORDER BY bulan, produk;Output yang Dihasilkan:
bulan | produk | pendapatan | total_rows | total_range
------------+------------+-------------+-------------+-------------
2026-01-01 | Gula Pasir | 3200000.00 | 3200000.00 | 16500000.00
2026-01-01 | Kopi Gayo | 9200000.00 | 12400000.00 | 16500000.00
2026-01-01 | Teh Melati | 4100000.00 | 13300000.00 | 16500000.00
2026-02-01 | Gula Pasir | 3600000.00 | 7700000.00 | 17700000.00
2026-02-01 | Kopi Gayo | 9800000.00 | 13400000.00 | 17700000.00
2026-02-01 | Teh Melati | 4300000.00 | 14100000.00 | 17700000.00
2026-03-01 | Gula Pasir | 3100000.00 | 7400000.00 | 16600000.00
2026-03-01 | Kopi Gayo | 8900000.00 | 12000000.00 | 16600000.00
2026-03-01 | Teh Melati | 4600000.00 | 13500000.00 | 16600000.00
2026-04-01 | Gula Pasir | 3800000.00 | 8400000.00 | 18400000.00
2026-04-01 | Kopi Gayo | 10200000.00 | 14000000.00 | 18400000.00
2026-04-01 | Teh Melati | 4400000.00 | 14600000.00 | 18400000.00
(12 rows)Dua kolom itu memberi hasil yang jauh berbeda untuk baris yang sama. Untuk baris Gula Pasir Februari, total_rows bernilai 7.700.000: satu baris fisik sebelumnya (baris Teh Melati Januari, 4.100.000) ditambah barisnya sendiri (3.600.000). Sebaliknya total_range bernilai 17.700.000: rentang nilainya adalah “dari satu hari sebelum 1 Februari sampai 1 Februari”, dan karena bulan-bulan lain berjarak lebih dari satu hari, rentang itu hanya menampung semua peer Februari — ketiga baris Februari menerima total bulan Februari utuh. Inilah watak kedua mode tersebut: ROWS menjawab “baris mana saja”, RANGE menjawab “nilai sampai sejauh mana”.
Dua catatan teknis ikut terbawa dari query di atas. Pertama, offset untuk kolom bertipe date harus ditulis sebagai interval — menulis RANGE BETWEEN 1 PRECEDING dengan angka bulat membuat PostgreSQL menolaknya dengan pesan RANGE with offset PRECEDING/FOLLOWING is not supported for column type date and offset type integer; gantilah menjadi INTERVAL '1 day' PRECEDING (atau offset numerik bila kolom urutnya bertipe angka). Kedua, offset pada mode RANGE menuntut ORDER BY dengan tepat satu kolom, sehingga pemecah urut seperti produk tidak bisa ditambahkan di jendela w_range.
Sintaks Spesifikasi Frame #
Batas-batas frame ditulis dengan lima bentuk dasar; keduanya dipisahkan kata AND, dan mode (ROWS, RANGE, atau GROUPS) ditulis paling depan:
| Batas | Makna |
|---|---|
UNBOUNDED PRECEDING | baris pertama partisi |
n PRECEDING | n baris sebelum baris ini (ROWS), n satuan nilai ke belakang (RANGE), atau n kelompok peer ke belakang (GROUPS) |
CURRENT ROW | baris saat ini — pada mode RANGE, termasuk seluruh peer-nya |
n FOLLOWING | kebalikan dari n PRECEDING, ke arah belakang partisi |
UNBOUNDED FOLLOWING | baris terakhir partisi |
Query berikut memamerkan empat kombinasi yang paling sering dipakai, semuanya pada rangkaian Kopi Gayo yang bulannya unik sehingga perilaku ROWS terbaca tanpa efek peer:
-- galeri batas frame pada rangkaian Kopi Gayo (empat bulan, bulan unik)
SELECT bulan,
pendapatan,
sum(pendapatan) OVER (ORDER BY bulan
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS kumulatif,
sum(pendapatan) OVER (ORDER BY bulan
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS tengah,
sum(pendapatan) OVER (ORDER BY bulan
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS sisa,
sum(pendapatan) OVER (ORDER BY bulan
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS seluruh_partisi
FROM penjualan_bulanan
WHERE produk = 'Kopi Gayo'
ORDER BY bulan;Output yang Dihasilkan:
bulan | pendapatan | kumulatif | tengah | sisa | seluruh_partisi
------------+-------------+-------------+-------------+-------------+-----------------
2026-01-01 | 9200000.00 | 9200000.00 | 19000000.00 | 38100000.00 | 38100000.00
2026-02-01 | 9800000.00 | 19000000.00 | 27900000.00 | 28900000.00 | 38100000.00
2026-03-01 | 8900000.00 | 27900000.00 | 28900000.00 | 19100000.00 | 38100000.00
2026-04-01 | 10200000.00 | 38100000.00 | 19100000.00 | 10200000.00 | 38100000.00
(4 rows)Empat kolom itu adalah empat sudut pandang atas rangkaian yang sama. kumulatif tumbuh dari awal sampai baris ini — pola running total. tengah menjumlahkan satu baris sebelum sampai satu baris sesudah — jendela terpusat yang dipakai untuk merata-ratakan tanpa menunda hasil (di akhir rangkaian, tepi kanannya terpotong: April hanya menjumlahkan Maret dan April). sisa menghitung dari baris ini sampai akhir partisi — berguna untuk “sisa target yang belum tercapai”. seluruh_partisi menjumlahkan semuanya dan identik dengan OVER () — frame selengkap itu jarang ditulis panjang, tetapi berguna sebagai pembanding saat belajar. Sebagai pintasan, bila hanya batas awal yang ditulis tanpa kata BETWEEN, batas akhirnya otomatis CURRENT ROW: ROWS 2 PRECEDING setara dengan ROWS BETWEEN 2 PRECEDING AND CURRENT ROW (frame rata-rata bergerak di chapter sebelumnya boleh ditulis pendek begitu), dan ROWS UNBOUNDED PRECEDING setara dengan bentuk kumulatif penuh sampai baris saat ini. Mode ketiga, GROUPS, menghitung batas dalam satuan kelompok peer — GROUPS BETWEEN 1 PRECEDING AND CURRENT ROW berarti “kelompok nilai sebelumnya ditambah kelompok nilai sekarang” — dan menjadi pilihan alami saat Anda ingin frame bergerak per kelompok tanggal tanpa menghitung satuan nilai seperti pada RANGE.
Offset Tanpa ORDER BY Ditolak #
Batas berupa offset (n PRECEDING/n FOLLOWING) membutuhkan pengertian “berapa jauh ke belakang atau ke depan” — dan jarak hanya bermakna bila ada kolom urut. PostgreSQL karena itu menolak frame offset yang dibiarkan tanpa ORDER BY, sebagaimana dicoba query berikut:
-- frame dengan offset PRECEDING tetapi tanpa ORDER BY: PostgreSQL menolak
SELECT bulan,
sum(pendapatan) OVER (RANGE BETWEEN 1 PRECEDING AND CURRENT ROW) AS total_range
FROM penjualan_bulanan;Output yang Dihasilkan:
psql:frame-tanpa-order-by.sql:4: ERROR: RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column
LINE 2: sum(pendapatan) OVER (RANGE BETWEEN 1 PRECEDING AND C...
^Pesan RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column menyebut syaratnya lugas: mode RANGE dengan offset menuntut tepat satu kolom urut — query ini bahkan tidak punya satu pun. Yang menarik, mode ROWS dengan offset tanpa ORDER BY justru diterima PostgreSQL: baris-baris diproses dalam urutan kedatangan dari rencana eksekusi, sehingga “satu baris sebelumnya” tetap terhitung meskipun tidak terdefinisi secara logis. Perilaku seperti itu layak dipakai hanya saat urutan memang tidak bermakna; untuk analisis deret waktu, selalu sertakan ORDER BY.
EXCLUDE: Membuang Bagian dari Frame #
Fitur penutup spesifikasi frame adalah klausa EXCLUDE (tersedia sejak PostgreSQL 11), yang membuang sebagian baris dari frame yang sudah terbentuk. Dua varian yang paling sering dipakai: EXCLUDE CURRENT ROW membuang baris yang sedang diproses, dan EXCLUDE TIES membuang peer-nya baris tersebut tetapi mempertahankan barisnya sendiri:
-- EXCLUDE: mengeluarkan baris tertentu dari frame berbasis RANGE
SELECT bulan,
produk,
pendapatan,
sum(pendapatan) OVER (ORDER BY bulan
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS biasa,
sum(pendapatan) OVER (ORDER BY bulan
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
EXCLUDE CURRENT ROW) AS tanpa_baris_ini,
sum(pendapatan) OVER (ORDER BY bulan
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
EXCLUDE TIES) AS tanpa_peer
FROM penjualan_bulanan
ORDER BY bulan, produk;Output yang Dihasilkan:
bulan | produk | pendapatan | biasa | tanpa_baris_ini | tanpa_peer
------------+------------+-------------+-------------+-----------------+-------------
2026-01-01 | Gula Pasir | 3200000.00 | 16500000.00 | 13300000.00 | 3200000.00
2026-01-01 | Kopi Gayo | 9200000.00 | 16500000.00 | 7300000.00 | 9200000.00
2026-01-01 | Teh Melati | 4100000.00 | 16500000.00 | 12400000.00 | 4100000.00
2026-02-01 | Gula Pasir | 3600000.00 | 34200000.00 | 30600000.00 | 20100000.00
2026-02-01 | Kopi Gayo | 9800000.00 | 34200000.00 | 24400000.00 | 26300000.00
2026-02-01 | Teh Melati | 4300000.00 | 34200000.00 | 29900000.00 | 20800000.00
2026-03-01 | Gula Pasir | 3100000.00 | 50800000.00 | 47700000.00 | 37300000.00
2026-03-01 | Kopi Gayo | 8900000.00 | 50800000.00 | 41900000.00 | 43100000.00
2026-03-01 | Teh Melati | 4600000.00 | 50800000.00 | 46200000.00 | 38800000.00
2026-04-01 | Gula Pasir | 3800000.00 | 69200000.00 | 65400000.00 | 54600000.00
2026-04-01 | Kopi Gayo | 10200000.00 | 69200000.00 | 59000000.00 | 61000000.00
2026-04-01 | Teh Melati | 4400000.00 | 69200000.00 | 64800000.00 | 55200000.00
(12 rows)Ketiga kolom memakai frame yang sama — kumulatif RANGE sampai baris saat ini — tetapi isinya bergeser mengikuti bagian yang dibuang. Kolom tanpa_baris_ini untuk Kopi Gayo Januari bernilai 7.300.000: total Januari (16.500.000) dikurangi barisnya sendiri (9.200.000), dengan dua peer Januari tetap ikut. Kolom tanpa_peer bernilai 9.200.000: hanya barisnya sendiri yang tersisa dari kelompok Januari, karena peer-nya dibuang — dan mulai Februari kolom ini berisi total bulan-bulan sebelumnya ditambah barisnya sendiri (misalnya Kopi Gayo Februari: 16.500.000 + 9.800.000). Dua varian lainnya: EXCLUDE GROUP membuang baris ini beserta seluruh peer-nya, dan EXCLUDE NO OTHERS adalah perilaku bawaan yang tidak membuang apa pun. Kombinasi RANGE ... EXCLUDE TIES ini adalah resep klasik untuk menghitung ulang angka bulanan “tanpa menghitung dua kali” saat baris-baris sebulan harus berbagi satu frame.
Kotak perkakas window function Anda kini lengkap: PARTITION BY memilih rangkaian, ORDER BY mengarahkan urutan, frame menentukan jangkauan per baris, dan EXCLUDE memplesinkan tepinya. Satu hal yang belum kita lakukan: memakai semuanya sekaligus pada pertanyaan analisis yang nyata. Chapter penutup section ini, Window Function untuk Analisis
, merangkai running total, rata-rata bergerak, LAG, dan ROW_NUMBER menjadi lima query analisis yang siap dipakai di laporan sungguhan.
Referensi #
- Window Function Expressions — spesifikasi sintaks frame, mode ROWS/RANGE/GROUPS, dan EXCLUDE.
- Window Functions — daftar fungsi jendela dan contoh pemakaian frame.
- SELECT (SQL Reference) — sintaks klausa WINDOW untuk memberi nama definisi jendela.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
buat-tabel.sql
Unduh berkas-- tabel latihan: pendapatan bulanan per produk, Januari-April 2026
-- kolom bulan sengaja memuat nilai kembar: tiga produk per bulan yang sama
CREATE TABLE penjualan_bulanan (
id integer PRIMARY KEY,
produk text NOT NULL,
bulan date NOT NULL,
pendapatan numeric(12,2) NOT NULL
);
INSERT INTO penjualan_bulanan (id, produk, bulan, pendapatan) VALUES
( 1, 'Gula Pasir', DATE '2026-01-01', 3200000.00),
( 2, 'Kopi Gayo', DATE '2026-01-01', 9200000.00),
( 3, 'Teh Melati', DATE '2026-01-01', 4100000.00),
( 4, 'Gula Pasir', DATE '2026-02-01', 3600000.00),
( 5, 'Kopi Gayo', DATE '2026-02-01', 9800000.00),
( 6, 'Teh Melati', DATE '2026-02-01', 4300000.00),
( 7, 'Gula Pasir', DATE '2026-03-01', 3100000.00),
( 8, 'Kopi Gayo', DATE '2026-03-01', 8900000.00),
( 9, 'Teh Melati', DATE '2026-03-01', 4600000.00),
(10, 'Gula Pasir', DATE '2026-04-01', 3800000.00),
(11, 'Kopi Gayo', DATE '2026-04-01', 10200000.00),
(12, 'Teh Melati', DATE '2026-04-01', 4400000.00);
SELECT id, produk, bulan, pendapatan
FROM penjualan_bulanan
ORDER BY bulan, produk;
exclude-frame.sql
Unduh berkas-- EXCLUDE: mengeluarkan baris tertentu dari frame berbasis RANGE
SELECT bulan,
produk,
pendapatan,
sum(pendapatan) OVER (ORDER BY bulan
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS biasa,
sum(pendapatan) OVER (ORDER BY bulan
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
EXCLUDE CURRENT ROW) AS tanpa_baris_ini,
sum(pendapatan) OVER (ORDER BY bulan
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
EXCLUDE TIES) AS tanpa_peer
FROM penjualan_bulanan
ORDER BY bulan, produk;
frame-default.sql
Unduh berkas-- frame default: tanpa ORDER BY, dengan ORDER BY, dan eksplisit ROWS
SELECT bulan,
produk,
pendapatan,
sum(pendapatan) OVER () AS total_semua,
sum(pendapatan) OVER (ORDER BY bulan) AS kumulatif_default,
sum(pendapatan) OVER (ORDER BY bulan, produk
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS baris_demi_baris
FROM penjualan_bulanan
ORDER BY bulan, produk;
frame-tanpa-order-by.sql
Unduh berkas-- frame dengan offset PRECEDING tetapi tanpa ORDER BY: PostgreSQL menolak
SELECT bulan,
sum(pendapatan) OVER (RANGE BETWEEN 1 PRECEDING AND CURRENT ROW) AS total_range
FROM penjualan_bulanan;
rows-vs-range.sql
Unduh berkas-- ROWS vs RANGE pada data dengan bulan kembar: posisi fisik atau kelompok nilai
SELECT bulan,
produk,
pendapatan,
sum(pendapatan) OVER w_rows AS total_rows,
sum(pendapatan) OVER w_range AS total_range
FROM penjualan_bulanan
WINDOW w_rows AS (ORDER BY bulan ROWS BETWEEN 1 PRECEDING AND CURRENT ROW),
w_range AS (ORDER BY bulan RANGE BETWEEN INTERVAL '1 day' PRECEDING AND CURRENT ROW)
ORDER BY bulan, produk;
spesifikasi-frame.sql
Unduh berkas-- galeri batas frame pada rangkaian Kopi Gayo (empat bulan, bulan unik)
SELECT bulan,
pendapatan,
sum(pendapatan) OVER (ORDER BY bulan
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS kumulatif,
sum(pendapatan) OVER (ORDER BY bulan
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS tengah,
sum(pendapatan) OVER (ORDER BY bulan
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS sisa,
sum(pendapatan) OVER (ORDER BY bulan
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS seluruh_partisi
FROM penjualan_bulanan
WHERE produk = 'Kopi Gayo'
ORDER BY bulan;