Soal 1Manakah yang diperlukan saat kamu menulis subkueri (tabel turunan) di klausa FROM?
Subkueri ② — Tabel Turunan, Subkueri SELECT, CREATE / INSERT SELECT
Pelajari tabel turunan SQL, subkueri di klausa SELECT, perpaduan dengan CASE, dan CREATE / INSERT SELECT — praktik langsung dengan data karyawan dan penjualan di browser kamu.
Data yang dipakai di artikel ini — employee / department / sales
Sebelumnya kamu memakai subkueri di WHERE.
Di artikel ini kamu akan membahas empat penerapan secara berurutan: menaruh subkueri di klausa `FROM` (tabel turunan), menulisnya di kolom `SELECT`, memadukannya dengan `CASE`, dan membangun tabel baru dari hasil subkueri.
Materinya adalah tiga tabel data karyawan.
Dengan employee (30 karyawan), department (6 departemen), dan sales (50 baris penjualan), kamu akan membangun tabel agregat per departemen dan menyandingkan total penjualan tiap karyawan sebagai sebuah kolom.
Tabel turunan di FROM — perlakukan hasil subkueri sebagai satu tabel
Tabel turunan adalah cara menulis subkueri di klausa FROM sehingga hasilnya diperlakukan sebagai satu tabel virtual.
Kamu bisa lebih dulu membangun "rata-rata gaji per departemen" sebagai tabel agregat, lalu menerapkan JOIN atau WHERE lebih lanjut pada tabel itu.
Ini berguna saat kamu ingin mempersempit hasil yang sudah diagregasi satu langkah lagi.
Aturan kunci untuk tabel turunan adalah kamu wajib memberinya alias.
Tulis AS alias seperti FROM (SELECT ...) AS ds (SQLite juga memperbolehkan menghilangkan AS) — tanpa itu kamu akan dapat error.
Melalui alias itu kamu mengacu ke kolom tabel turunan, seperti ds.avg_salary.
-- Tabel turunan di FROM: agregasi jumlah orang dan rata-rata gaji per departemen, lalu join dengan department
SELECT d.dept_name, ds.headcount, ds.avg_salary
FROM (
SELECT dept_id, COUNT(*) AS headcount, AVG(salary) AS avg_salary
FROM employee
WHERE dept_id IS NOT NULL
GROUP BY dept_id
) AS ds
JOIN department d ON d.dept_id = ds.dept_id
ORDER BY ds.avg_salary DESC;
Subkueri di klausa SELECT — sematkan satu nilai sebagai kolom
Ketika kamu menulis subkueri skalar di daftar kolom SELECT, kamu bisa menambahkan kolom yang nilainya dihitung satu per baris.
Taruh (SELECT SUM(sale.amount) FROM sales sale WHERE sale.emp_id = emp.emp_id) di sebuah kolom, dan kamu bisa menyandingkan "total penjualan karyawan itu" sebagai satu kolom per karyawan.
Ini adalah subkueri terkorelasi yang mengacu ke emp.emp_id di luar.
-- Subkueri di klausa SELECT: tambahkan total penjualan tiap karyawan sebagai satu kolom
SELECT emp.name,
COALESCE(
(SELECT SUM(sale.amount) FROM sales sale WHERE sale.emp_id = emp.emp_id),
0
) AS total_amount
FROM employee emp
ORDER BY emp.emp_id
LIMIT 6;
Karyawan tanpa penjualan membuat subkueri mengembalikan NULL, jadi menggantinya dengan 0 memakai COALESCE(..., 0) membuat tabel lebih mudah dibaca.
Subkueri di klausa SELECT juga harus muat dalam satu baris dan satu kolom.
Memadukan dengan CASE — tempelkan label percabangan berdasarkan nilai subkueri
Subkueri di klausa SELECT bekerja sama baiknya sebagai kondisi di CASE.
Kamu bisa membangun kolom peringkat seperti "jika total penjualan 1.500.000 atau lebih maka High, jika lebih dari 0 maka Mid, selain itu None" dengan menilai nilai subkueri pakai CASE WHEN.
Perhatikan bahwa kamu harus mengulang subkueri yang sama di tiap WHEN CASE (jika keterbacaan yang diutamakan, ada juga cara menulisnya hanya sekali dengan WITH (Common Table Expressions), yang akan kamu pelajari di bab berikutnya).
Di artikel ini kamu akan membahas bentuk dasar memadukan subkueri dan CASE secara langsung.
-- Klasifikasikan karyawan berdasarkan jumlah penjualan mereka
SELECT emp.name,
(SELECT COUNT(*) FROM sales sale WHERE sale.emp_id = emp.emp_id) AS sale_count,
CASE
WHEN (SELECT COUNT(*) FROM sales sale WHERE sale.emp_id = emp.emp_id) >= 4 THEN 'Frequent'
WHEN (SELECT COUNT(*) FROM sales sale WHERE sale.emp_id = emp.emp_id) >= 1 THEN 'Occasional'
ELSE 'None'
END AS activity
FROM employee emp
ORDER BY sale_count DESC, emp.emp_id
LIMIT 8;
CREATE / INSERT SELECT — jadikan hasil subkueri sebuah tabel
Menulis CREATE TABLE tabel_baru AS SELECT ... memungkinkanmu menyimpan hasil SELECT langsung sebagai tabel baru (CTAS: Create Table As Select).
Ini sering dipakai saat kamu ingin menyimpan hasil agregat sebagai snapshot.
Ketika kamu ingin menambahkan baris ke tabel yang sudah ada, pakai INSERT INTO tabel_lama SELECT ... untuk menambahkan hasil SELECT secara massal.
Ini adalah operasi tulis yang membuat tabel atau menambahkan baris.
Di artikel ini kamu akan memakai tabel kerja sekali pakai top_seller untuk agregasi.
Supaya kamu mendapat hasil yang sama berapa kali pun dijalankan, kamu akan membersihkan tabel kerja dengan DROP TABLE IF EXISTS sebelum membuatnya ulang.
INSERT massal lebih cepat
INSERT INTO tabel SELECT ... menyisipkan baris target sekaligus dalam satu pernyataan.
Dibandingkan mengulang INSERT INTO tabel VALUES (...) untuk tiap baris, parsing SQL, pembaruan indeks, dan penanganan transaksi terjadi hanya sekali, jadi semakin banyak baris yang kamu sisipkan, semakin cepat jadinya.
Saat menyalin atau memindahkan tabel lain atau hasil agregat, lebih baik pakai INSERT ... SELECT massal ketimbang mengulang INSERT satu baris demi satu baris.
-- Simpan agregat per departemen ke tabel snapshot
DROP TABLE IF EXISTS dept_summary;
CREATE TABLE dept_summary AS
SELECT dept_id, COUNT(*) AS headcount, AVG(salary) AS avg_salary
FROM employee
WHERE dept_id IS NOT NULL
GROUP BY dept_id;
SELECT * FROM dept_summary ORDER BY avg_salary DESC;
Cek Pemahaman
Jawab setiap pertanyaan satu per satu.
Soal 2Di SELECT emp.name, (SELECT SUM(sale.amount) FROM sales sale WHERE sale.emp_id = emp.emp_id) AS total FROM employee emp, apa yang terjadi pada kolom total untuk karyawan yang sama sekali tidak punya penjualan?
Soal 3Manakah deskripsi yang benar tentang CREATE TABLE top_seller AS SELECT ...?