Free Web Book

Belajar SQL Basic
Dari Nol Sampai Siap
Ke Proyek Nyata

Kurikulum terstruktur + panduan tools + referensi video — semua dalam satu tempat. Cocok untuk pemula yang ingin serius menguasai SQL.

📖 10 Bab 🛠 7+ Tools 🎥 10+ Referensi Video ⏱ ~4 Jam Belajar
1

Apa Itu Database & SQL?

Sebelum menulis query, kamu harus paham dulu apa itu database dan kenapa SQL jadi bahasa paling penting di dunia data.

Database Relational

Database relational menyimpan data dalam bentuk tabel (baris & kolom), di mana satu tabel bisa berhubungan dengan tabel lain melalui key. Bayangkan spreadsheet yang saling terhubung.

-- Contoh struktur tabel CREATE TABLE users ( id INTEGER PRIMARY KEY, name VARCHAR(100), email VARCHAR(255) ); CREATE TABLE orders ( id INTEGER PRIMARY KEY, user_id INTEGER REFERENCES users(id), amount DECIMAL(10,2), created_at TIMESTAMP );

SQL: Bahasa Universal Data

SQL (Structured Query Language) adalah bahasa standar untuk berkomunikasi dengan database relational. Hampir semua RDBMS (PostgreSQL, MySQL, SQL Server, SQLite) menggunakan SQL dengan sedikit perbedaan dialek.

💡 Catatan: SQL itu declarative — kamu bilang APA yang mau diambil, bukan BAGAIMANA cara mengambilnya. Mesin database yang urus sisanya.

RDBMS Populer

NamaLisensiCocok UntukKeunikan
PostgreSQLOpen SourceProduction, analyticsFitur paling lengkap, extensible
MySQLOpen SourceWeb apps (WordPress, Laravel)Populer, cepat untuk read-heavy
SQLitePublic DomainMobile, embedded, local devServerless, file-based
SQL ServerProprietaryEnterprise .NET ecosystemIntegrasi dengan Microsoft stack
2

Persiapan & Tools

Bagian paling membingungkan bagi pemula: pilih tools yang mana? Tenang, kita bahas satu per satu.

Rekomendasi Setup Pemula

Untuk belajar, cukup install SQLite (nol konfigurasi) + DBeaver (GUI universal). Nanti setelah paham dasar, bisa ekspansi ke PostgreSQL/MySQL.

✅ Rekomendasi: Mulai dengan SQLite + DBeaver. Tidak perlu install server, tidak perlu config user/password. Langsung praktik.

Tools Database GUI

🦫

DBeaver

Universal GUI — support semua database. Gratis, open source, cross-platform.

Rekomendasi #1
🐬

MySQL Workbench

Official GUI dari MySQL. Cocok kalau fokus belajar MySQL.

MySQL
🐘

pgAdmin

Official GUI untuk PostgreSQL. Web-based, fitur administrasi lengkap.

PostgreSQL
🗄️

DB Browser for SQLite

GUI ringan khusus SQLite. Portable, nggak perlu installasi rumit.

SQLite
🧩

TablePlus

GUI modern & cepat. Support banyak database. Native Mac, ada trial.

Modern UI
📟

Azure Data Studio

Dari Microsoft, ringan. Cocok untuk SQL Server & PostgreSQL.

Cross-platform

Command Line (CLI)

Tools GUI memang nyaman, tapi suatu saat kamu pasti butuh CLI. Ada kalanya server nggak punya GUI, dan kamu harus debug pakai terminal.

DatabaseCLIContoh Koneksi
PostgreSQLpsqlpsql -U postgres -d mydb
MySQLmysqlmysql -u root -p mydb
SQLitesqlite3sqlite3 mydb.sqlite

VS Code Extensions

Buat yang pakai VS Code, install extension ini biar workflow makin mulus:

3

SELECT & WHERE

Dua kata yang paling sering kamu pakai dalam SQL. SELECT buat ambil data, WHERE buat filter data. Ini adalah fondasi dari segalanya.

SELECT Dasar

Gunakan SELECT untuk mengambil kolom tertentu dari sebuah tabel.

-- Ambil semua kolom SELECT * FROM users; -- Ambil kolom spesifik SELECT name, email FROM users; -- Kolom dengan alias SELECT name AS nama_pengguna FROM users;

WHERE: Filter Data

WHERE membatasi baris yang dikembalikan berdasarkan kondisi.

SELECT * FROM products WHERE price > 100000; SELECT * FROM orders WHERE status = 'paid' AND created_at >= '2025-01-01';

Operator Perbandingan

OperatorArtiContoh
=Sama denganWHERE name = 'Budi'
<> atau !=Tidak samaWHERE status <> 'canceled'
>, <Lebih dari / Kurang dariWHERE price > 50000
>=, <=Lebih/Kurang dari atau samaWHERE age >= 17
IS NULLNilai NULLWHERE deleted_at IS NULL
IS NOT NULLBukan NULLWHERE phone IS NOT NULL
⚠️ Hati-hati dengan NULL: NULL bukan angka 0 atau string kosong. NULL artinya "tidak diketahui". Operasi NULL = NULL hasilnya false. Selalu gunakan IS NULL untuk mengecek.

Logical Operators

Gabungkan kondisi dengan AND, OR, dan NOT.

SELECT * FROM products WHERE category = 'Elektronik' AND (price BETWEEN 100000 AND 500000) AND NOT stock = 0;
4

Filtering & Sorting

Data mentah jarang berguna tanpa diurutkan dan difilter dengan tepat. Di bab ini kita akan merapikan hasil query.

ORDER BY — Mengurutkan Hasil

SELECT name, price FROM products ORDER BY price DESC; -- Multi-level sorting SELECT * FROM users ORDER BY status ASC, created_at DESC;

LIMIT & OFFSET — Paginasi

SELECT * FROM products ORDER BY price DESC LIMIT 10; -- Halaman 2 (skip 10 baris pertama) SELECT * FROM products ORDER BY price DESC LIMIT 10 OFFSET 10;

DISTINCT — Hilangkan Duplikat

SELECT DISTINCT category FROM products; SELECT DISTINCT city, province FROM addresses;

Operator Khusus untuk Filtering

-- BETWEEN: rentang nilai SELECT * FROM orders WHERE amount BETWEEN 50000 AND 500000; -- IN: salah satu dari daftar SELECT * FROM products WHERE category IN ('Elektronik', 'Fashion', 'Aksesoris'); -- LIKE: pencocokan pola SELECT * FROM users WHERE name LIKE '%budi%'; -- % = wildcard (0+ karakter) -- _ = tepat 1 karakter
5

JOINs

Di sinilah SQL mulai terasa powerful-nya. JOIN menggabungkan data dari beberapa tabel dalam satu query.

INNER JOIN

Hanya mengembalikan baris yang punya kecocokan di kedua tabel.

SELECT u.name, o.amount, o.created_at FROM users u INNER JOIN orders o ON u.id = o.user_id;

LEFT JOIN

Semua baris dari tabel kiri dipertahankan. Jika tidak ada kecocokan di tabel kanan, kolomnya akan NULL.

SELECT u.name, COUNT(o.id) AS total_order FROM users u LEFT JOIN orders o ON u.id = o.user_id GROUP BY u.id, u.name;
💡 Visualisasi JOIN: INNER JOIN = irisan Venn. LEFT JOIN = lingkaran kiri penuh. Kalau bingung, gambar diagram Venn dulu sebelum nulis query.

RIGHT & FULL JOIN

-- RIGHT JOIN: kebalikan LEFT SELECT * FROM orders o RIGHT JOIN users u ON u.id = o.user_id; -- FULL JOIN: semua baris dari kedua tabel -- (tidak semua database support — PostgreSQL support, MySQL tidak) SELECT * FROM users u FULL JOIN orders o ON u.id = o.user_id;

Self JOIN

JOIN tabel dengan dirinya sendiri. Berguna untuk data hierarki (kategori, employee-manager).

SELECT e.name AS employee, m.name AS manager FROM employees e LEFT JOIN employees m ON e.manager_id = m.id;
6

Aggregate Functions & GROUP BY

Data mentah perlu diringkas. Aggregate functions mengubah banyak baris menjadi satu nilai ringkasan.

Fungsi Agregat Dasar

FungsiKegunaanContoh
COUNT()Menghitung jumlah barisCOUNT(*) AS total_user
SUM()Total nilai numerikSUM(amount) AS revenue
AVG()Rata-rata nilaiAVG(price) AS avg_price
MIN()Nilai terkecilMIN(price) AS termurah
MAX()Nilai terbesarMAX(price) AS termahal
SELECT COUNT(*) AS total_transaksi, SUM(amount) AS total_pendapatan, AVG(amount) AS rata_rata, MIN(amount) AS transaksi_terkecil, MAX(amount) AS transaksi_terbesar FROM orders WHERE status = 'paid';

GROUP BY — Kelompokkan Data

GROUP BY membagi data menjadi grup berdasarkan nilai kolom, lalu fungsi agregat dijalankan per grup.

SELECT category, COUNT(*) AS jumlah_produk, SUM(stock) AS total_stok FROM products GROUP BY category;

HAVING — Filter Hasil Agregasi

HAVING mirip WHERE, tapi untuk hasil agregasi. WHERE filter baris sebelum GROUP BY, HAVING filter setelah GROUP BY.

SELECT user_id, COUNT(*) AS total_order, SUM(amount) AS total_belanja FROM orders WHERE status = 'paid' GROUP BY user_id HAVING COUNT(*) >= 3 ORDER BY total_belanja DESC;
⚠️ Urutan Eksekusi SQL: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT. Hafalkan urutan ini, karena banyak error terjadi karena salah paham urutan eksekusi.
7

Subqueries & CTEs

Kadang kamu perlu query di dalam query. Subquery dan CTE (Common Table Expression) adalah teknik untuk membuat query bertingkat yang lebih terstruktur.

Subquery di WHERE

SELECT name, price FROM products WHERE price > ( SELECT AVG(price) FROM products ); -- IN dengan subquery SELECT name FROM users WHERE id IN ( SELECT user_id FROM orders WHERE amount > 1000000 );

Correlated Subquery

Subquery yang referensi kolom dari outer query. Dijalankan per baris — hati-hati soal performa.

SELECT p.name, p.price, p.category FROM products p WHERE p.price = ( SELECT MAX(price) FROM products WHERE category = p.category );

EXISTS / NOT EXISTS

Lebih efisien daripada IN untuk kasus tertentu — berhenti begitu nemu kecocokan pertama.

SELECT u.name, u.email FROM users u WHERE EXISTS ( SELECT 1 FROM orders o WHERE o.user_id = u.id );

CTE (WITH)

CTE membuat query sementara yang bisa kamu pakai di SELECT utama. Jauh lebih rapi daripada subquery bertingkat.

WITH top_customers AS ( SELECT user_id, SUM(amount) AS total_spent FROM orders GROUP BY user_id HAVING SUM(amount) > 5000000 ) SELECT u.name, tc.total_spent FROM users u INNER JOIN top_customers tc ON u.id = tc.user_id ORDER BY tc.total_spent DESC;
✅ Tip: Kalau subquery-mu mulai bersarang 3 tingkat, pakai CTE. Jauh lebih mudah dibaca dan di-debug.
8

Data Manipulation (INSERT, UPDATE, DELETE)

SELECT untuk membaca, tapi kapan kita nulis data? Di sinilah DML (Data Manipulation Language) berperan.

INSERT — Menambah Data

INSERT INTO users (name, email, created_at) VALUES ('Budi Santoso', 'budi@email.com', '2025-06-01'); -- Insert banyak baris sekaligus INSERT INTO products (name, price, category) VALUES ('Kaos Polos', 75000, 'Fashion'), ('Kemeja Flanel', 150000, 'Fashion'), ('Topi Baseball', 45000, 'Aksesoris');

UPDATE — Mengubah Data

UPDATE products SET price = 80000, updated_at = '2025-06-15' WHERE id = 1;
⚠️ SELALU pakai WHERE di UPDATE dan DELETE! Kalau lupa WHERE, semua baris akan berubah. Ini bukan mitos — ini error paling umum dan paling fatal.

DELETE — Menghapus Data

DELETE FROM products WHERE id = 1; -- Hapus semua baris (tapi tabel tetap ada) DELETE FROM logs; -- atau lebih cepat: TRUNCATE TABLE logs;

Transactions

Transaction memastikan beberapa operasi berjalan all or nothing. Kalau satu gagal, semuanya dibatalkan.

BEGIN; UPDATE accounts SET balance = balance - 100000 WHERE id = 1; UPDATE accounts SET balance = balance + 100000 WHERE id = 2; COMMIT; -- kalau ada error, pakai ROLLBACK;
9

Database Design & Normalisasi

Database yang dirancang dengan buruk akan membuat query jadi rumit dan lambat. Bab ini membahas prinsip desain yang benar.

Primary Key & Foreign Key

Primary Key adalah identitas unik setiap baris di tabel. Foreign Key menghubungkan tabel satu dengan yang lain.

CREATE TABLE categories ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL ); CREATE TABLE products ( id SERIAL PRIMARY KEY, name VARCHAR(200) NOT NULL, category_id INTEGER REFERENCES categories(id), price DECIMAL(12,2), created_at TIMESTAMP DEFAULT NOW() );

Normalisasi Database

Normalisasi adalah proses menghilangkan data duplikat dan memastikan integritas data.

BentukAturanContoh Pelanggaran
1NFSetiap kolom berisi 1 nilai (atomic)Kolom phone berisi "0811, 0822"
2NF1NF + semua kolom non-key tergantung pada seluruh primary keyTabel dengan PK komposit tapi kolom lain hanya tergantung 1 bagian PK
3NF2NF + tidak ada transitive dependencyKolom city_name tergantung city_id, bukan PK
💡 Praktik: Normalisasi sampai 3NF untuk sebagian besar aplikasi. Jangan terlalu over-normalize — terkadang denormalisasi ringan diperlukan untuk performa.

Entity Relationship Diagram (ERD)

Sebelum bikin tabel, gambar dulu ERD-nya. Hubungan antar entitas biasanya:

10

Performance & Best Practices

Query yang benar belum tentu query yang efisien. Bab ini membahas cara menulis SQL yang tidak hanya benar, tapi juga cepat.

EXPLAIN — Baca Rencana Eksekusi

EXPLAIN menunjukkan bagaimana database akan menjalankan query-mu. Ini adalah skill paling penting setelah bisa nulis query.

EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 42; -- Cari "Seq Scan" = full table scan (lambat) -- Cari "Index Scan" = pakai index (cepat)

Indexing

Index mempercepat pencarian dengan cara yang mirip indeks di buku. Tapi ada trade-off: nulis data jadi sedikit lebih lambat karena index harus diupdate.

CREATE INDEX idx_orders_user_id ON orders(user_id); -- Composite index untuk query multi-kolom CREATE INDEX idx_orders_user_status ON orders(user_id, status);

Common Mistakes

KesalahanSolusi
SELECT * di productionSebutkan kolom spesifik
N+1 query (loop query di aplikasi)Pakai JOIN atau batch query
Lupa WHERE di UPDATE/DELETESelalu double-check sebelum execute
Tidak pakai index untuk kolom yang sering difilterMonitor slow query & tambah index
Function di kolom di WHERE (WHERE YEAR(date) = 2025)Gunakan range: WHERE date >= '2025-01-01' AND date < '2026-01-01'
Ordering by kolom tanpa indexTambah index atau batasi hasil

Panduan Singkat Best Practices

Referensi Video YouTube

Video berikut melengkapi materi di atas. Tonton sesuai urutan bab untuk hasil maksimal.

🎬

Belajar SQL Dasar — Database & SELECT Query

Pengantar SQL dari awal: database, SELECT, WHERE, ORDER BY

📺 Web Programming UNPAS
🎬

SQL JOINs Explained with Examples

Visual explanation of INNER, LEFT, RIGHT, FULL JOIN with diagrams

📺 Joey Blue
🎬

SQL Aggregate Functions — COUNT, SUM, AVG, GROUP BY, HAVING

Praktik fungsi agregat dari dasar sampai mahir

📺 Dea Afrizal
🎬

Subqueries & CTEs in SQL

Kapan pakai subquery vs CTE, plus contoh use case nyata

📺 Programmer Zaman Now
🎬

Database Normalization — 1NF, 2NF, 3NF

Penjelasan normalisasi database dengan contoh studi kasus

📺 Dea Afrizal
🎬

SQL Indexing Explained (PostgreSQL)

Cara kerja index, kapan bikin index, dan bagaimana EXPLAIN bekerja

📺 Hussein Nasser
🎬

MySQL vs PostgreSQL — Which One to Choose?

Perbandingan lengkap dua RDBMS paling populer di dunia

📺 Web Programming UNPAS
🎬

SQL Transaction & Concurrency Control

BEGIN, COMMIT, ROLLBACK, isolation levels — konsep penting production

📺 TechWorld with Nana
🎬

SQL Window Functions (Advanced)

ROW_NUMBER, RANK, LAG, LEAD — bab lanjutan setelah kuasai dasar

📺 Programmer Zaman Now
🎬

Full SQL Course — FreeCodeCamp

Kursus SQL 4 jam gratis dari FreeCodeCamp, dari nol sampai mahir

📺 FreeCodeCamp.org

📋 Daftar Isi Lengkap

  1. Database & SQL
  2. Setup & Tools
  3. SELECT & WHERE
  4. Filtering & Sorting
  5. JOINs
  6. Aggregate Functions
  7. Subqueries & CTEs
  8. Data Manipulation
  9. Database Design
  10. Performance
  11. Referensi Video