Pivot table mengubah baris menjadi kolom: satu baris per grup, dan satu kolom untuk setiap nilai dari field lain, misalnya satu kolom per kuartal. Di SQL, Anda membuatnya dengan CASE di dalam fungsi agregat seperti SUM, lalu dikelompokkan berdasarkan apa yang mewakili setiap baris. Contoh-contohnya berjalan di PostgreSQL, MySQL, SQLite, dan SQL Server.
Cara membuat pivot table di SQL
Tulis satu agregat untuk setiap kolom output. CASE di dalamnya hanya meloloskan baris yang termasuk kolom tersebut, dan GROUP BY menghasilkan satu baris per grup:
SELECT
row_column,
SUM(CASE WHEN pivot_column = 'value 1' THEN amount ELSE 0 END) AS value_1,
SUM(CASE WHEN pivot_column = 'value 2' THEN amount ELSE 0 END) AS value_2
FROM table_name
GROUP BY row_column;
Di sini setiap produk mendapat satu baris, dengan jumlah unit per kuartal berdampingan:
-- Input: sales
-- product | quarter | units
-- ---------+---------+------
-- Keyboard | Q1 | 120
-- Keyboard | Q2 | 95
-- Monitor | Q1 | 40
-- Monitor | Q2 | 55
-- Mouse | Q2 | 210
SELECT
product,
SUM(CASE WHEN quarter = 'Q1' THEN units ELSE 0 END) AS q1,
SUM(CASE WHEN quarter = 'Q2' THEN units ELSE 0 END) AS q2
FROM sales
GROUP BY product
ORDER BY product;
-- Output:
-- product | q1 | q2
-- ---------+-----+----
-- Keyboard | 120 | 95
-- Monitor | 40 | 55
-- Mouse | 0 | 210
Aturan yang perlu diketahui
-
Anda sendiri yang menamai setiap kolom. SQL tidak bisa membuat kolom dari data, jadi kuartal ketiga butuh baris
CASEketiga. Jika daftar nilainya terus berubah, susun query-nya di kode aplikasi Anda. -
ELSE 0hanya untukSUMdan hitungan. Ini mengubah kombinasi yang tidak ada menjadi 0, bukan NULL. DenganAVG,MIN, atauMAX, hilangkanELSE, kalau tidak angka nol ikut dihitung sebagai nilai sungguhan:
-- Input: the sales table above
SELECT
product,
ROUND(AVG(CASE WHEN quarter = 'Q1' THEN units ELSE 0 END), 1) AS q1_else_0,
ROUND(AVG(CASE WHEN quarter = 'Q1' THEN units END), 1) AS q1_no_else
FROM sales
GROUP BY product
ORDER BY product;
-- Output:
-- product | q1_else_0 | q1_no_else
-- ---------+-----------+-----------
-- Keyboard | 60.0 | 120.0
-- Monitor | 20.0 | 40.0
-- Mouse | 0.0 | NULL
Sintaks alternatif
Anda juga akan menjumpai FILTER di PostgreSQL dan SQLite, serta operator PIVOT di SQL Server. Keduanya membiarkan kombinasi yang tidak ada sebagai NULL, bukan 0:
-- Input: the sales table above
-- PostgreSQL and SQLite
SELECT
product,
SUM(units) FILTER (WHERE quarter = 'Q1') AS q1,
SUM(units) FILTER (WHERE quarter = 'Q2') AS q2
FROM sales
GROUP BY product
ORDER BY product;
-- SQL Server
SELECT product, [Q1] AS q1, [Q2] AS q2
FROM (SELECT product, quarter, units FROM sales) AS src
PIVOT (SUM(units) FOR quarter IN ([Q1], [Q2])) AS p
ORDER BY product;
-- Output:
-- product | q1 | q2
-- ---------+------+----
-- Keyboard | 120 | 95
-- Monitor | 40 | 55
-- Mouse | NULL | 210
Di kode MySQL Anda akan sering melihat SUM(IF(quarter = 'Q1', units, 0)), cara yang lebih singkat untuk menulis versi CASE. Extension tablefunc di PostgreSQL juga punya fungsi crosstab(); lihat membuat pivot table di PostgreSQL dengan crosstab().
Kapan sebaiknya menggunakan pivot table?
Lakukan pivot saat daftar baris akan lebih mudah dibaca sebagai grid. Berikut alasan yang paling umum.
Membandingkan satu ukuran secara berdampingan
Letakkan nilai yang ingin dibandingkan (hari, kuartal, wilayah) bersebelahan dalam satu baris, alih-alih tersebar di daftar yang panjang.
Menampilkan lebih dari satu ukuran untuk setiap kolom
Setiap kolom output adalah agregat tersendiri, jadi Anda bisa memasangkannya: sesi dan pageview per perangkat, atau pesanan dan pendapatan per kanal.
Menghitung baris di setiap kategori
Untuk menghitung alih-alih menjumlahkan, jumlahkan 1 untuk setiap baris yang cocok, atau gunakan COUNT(CASE WHEN ... THEN 1 END): COUNT melewati NULL yang dihasilkan baris lainnya. Begini cara mendapatkan jumlah tugas per status atau tiket per prioritas.
Mengubah baris key-value menjadi kolom
Pengaturan dan atribut produk sering disimpan sebagai satu baris per nama dan nilai. Pivot dengan MAX(CASE ...) menghasilkan satu baris per item dengan satu kolom per atribut. MAX bekerja pada teks dan mengambil satu-satunya nilai di setiap grup.
Contoh nyata pivot table SQL
Rata-rata rating aplikasi per platform
Hilangkan ELSE saat menghitung rata-rata, agar aplikasi tanpa ulasan di suatu platform menampilkan NULL, bukan skor yang menyesatkan:
-- Input: reviews
-- app | platform | rating
-- ---------+----------+-------
-- Budgetly | iOS | 5
-- Budgetly | iOS | 4
-- Budgetly | Android | 3
-- FitTrack | Android | 4
-- FitTrack | Android | 5
-- In SQL Server, AVG of an integer column drops the decimals: use rating * 1.0
SELECT
app,
ROUND(AVG(CASE WHEN platform = 'iOS' THEN rating END), 1) AS ios,
ROUND(AVG(CASE WHEN platform = 'Android' THEN rating END), 1) AS android
FROM reviews
GROUP BY app
ORDER BY app;
-- Output:
-- app | ios | android
-- ---------+------+--------
-- Budgetly | 4.5 | 3.0
-- FitTrack | NULL | 4.5
Pesanan dan penjualan per kanal untuk setiap wilayah
Dua ukuran untuk setiap kanal, jumlah pesanan dan total:
-- Input: orders
-- id | region | channel | amount
-- ---+--------+---------+-------
-- 1 | North | web | 120.00
-- 2 | North | store | 80.00
-- 3 | North | web | 45.50
-- 4 | South | store | 210.00
-- 5 | South | store | 64.00
SELECT
region,
COUNT(CASE WHEN channel = 'web' THEN 1 END) AS web_orders,
SUM(CASE WHEN channel = 'web' THEN amount ELSE 0 END) AS web_sales,
COUNT(CASE WHEN channel = 'store' THEN 1 END) AS store_orders,
SUM(CASE WHEN channel = 'store' THEN amount ELSE 0 END) AS store_sales
FROM orders
GROUP BY region
ORDER BY region;
-- Output:
-- region | web_orders | web_sales | store_orders | store_sales
-- -------+------------+-----------+--------------+------------
-- North | 2 | 165.50 | 1 | 80.00
-- South | 0 | 0 | 2 | 274.00
Tiket support per agen berdasarkan prioritas
Satu hitungan untuk setiap prioritas, ditambah total. COUNT(*) tetap menghitung setiap baris dalam grup:
-- Input: tickets
-- id | agent | priority
-- ---+-------+---------
-- 1 | Priya | urgent
-- 2 | Priya | normal
-- 3 | Marco | normal
-- 4 | Priya | normal
-- 5 | Marco | low
SELECT
agent,
COUNT(CASE WHEN priority = 'low' THEN 1 END) AS low,
COUNT(CASE WHEN priority = 'normal' THEN 1 END) AS normal,
COUNT(CASE WHEN priority = 'urgent' THEN 1 END) AS urgent,
COUNT(*) AS total
FROM tickets
GROUP BY agent
ORDER BY agent;
-- Output:
-- agent | low | normal | urgent | total
-- ------+-----+--------+--------+------
-- Marco | 1 | 1 | 0 | 2
-- Priya | 0 | 2 | 1 | 3
Satu baris pengaturan per pengguna
Setiap pengaturan disimpan sebagai nama dan nilai. Pengguna yang tidak pernah mengaturnya mendapat NULL di kolom tersebut:
-- Input: user_settings
-- user_id | setting | value
-- --------+----------+--------------
-- 1 | theme | dark
-- 1 | language | en
-- 2 | language | de
-- 2 | timezone | Europe/Berlin
-- 3 | theme | light
SELECT
user_id,
MAX(CASE WHEN setting = 'theme' THEN value END) AS theme,
MAX(CASE WHEN setting = 'language' THEN value END) AS language,
MAX(CASE WHEN setting = 'timezone' THEN value END) AS timezone
FROM user_settings
GROUP BY user_id
ORDER BY user_id;
-- Output:
-- user_id | theme | language | timezone
-- --------+-------+----------+--------------
-- 1 | dark | en | NULL
-- 2 | NULL | de | Europe/Berlin
-- 3 | light | NULL | NULL
Bacaan lanjutan tentang pivot table
Di blog ini:
-
Cara pivot di PostgreSQL:
CASEdancrosstab()di PostgreSQL -
Membuat pivot table di PostgreSQL dengan crosstab(): extension
tablefuncsecara mendetail - Panduan statement CASE SQL: kondisi di dalam setiap kolom pivot
- Panduan GROUP BY SQL: mengelompokkan baris sebelum di-pivot
Dokumentasi resmi:
- PostgreSQL: ekspresi agregat dan FILTER serta crosstab()
- MySQL: operator CASE
- SQLite: fungsi agregat dan FILTER
- SQL Server: PIVOT dan UNPIVOT
Beekeeper Studio Adalah GUI Database Gratis & Open Source
Tool query & editor SQL terbaik yang pernah saya pakai. Semua yang saya butuhkan untuk mengelola database ada di sini. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio cepat, intuitif, dan mudah digunakan. Beekeeper mendukung banyak sekali database, dan berjalan mulus di Windows, Mac, dan Linux.
Apa Kata Pengguna tentang Beekeeper Studio
"Beekeeper Studio sepenuhnya menggantikan workflow SQL lama saya. Cepat, intuitif, dan membuat kerja dengan database kembali menyenangkan."
"Saya sudah mencoba banyak GUI database, tapi Beekeeper punya keseimbangan sempurna antara fitur dan kesederhanaan. Langsung jalan."