Artikel ini adalah bagian dari Kursus SQL, yang membantu Anda menguasai keterampilan SQL praktis dari nol, mulai dari dasar hingga kueri kompleks dan penyetelan SQL. Memakai tabel perf_sales 50.000 baris, pelajari tiga format penyimpanan tanggal (string ISO, julianday, unixepoch), agregasi berdasarkan tahun dan rentang dengan date() / strftime(), dan bagaimana tabel typed_strict menolak ketidakcocokan tipe — semua berjalan langsung di browser.
Tanggal disimpan baik sebagai string maupun sebagai angka, dan kamu membaca atau menghitungnya dengan fungsi seperti date() / strftime().
Di paruh pertama, kamu akan memakai kolom sale_date dari tabel penjualan perf_sales untuk memeriksa tiga format penyimpanan dan cara mengekstrak nilai; di paruh kedua, kamu akan membuat sendiri tabel STRICT untuk melihat apa yang terjadi ketika kamu memasukkan nilai yang tidak cocok dengan tipe yang dideklarasikan.
Sebelum latihan, lihat definisi kolom dan sampel data dari tabel perf_sales yang dipakai di artikel ini. (Jika kamu menjalankannya dengan benar, penjelasan akan muncul.)
① Jalankan PRAGMA table_info(perf_sales); untuk memeriksa definisi kolom.
② Jalankan SELECT * FROM perf_sales LIMIT 5; untuk mengintip 5 baris pertama. perf_sales memiliki banyak baris, jadi selalu tambahkan LIMIT.
SQL Editor
Jalankan query untuk melihat hasil
Schema
Tidak ada tabel
Tiga format penyimpanan tanggal — string ISO / julianday / unixepoch
Tanggal dan waktu bisa disimpan dalam tiga format utama.
Mudah dibaca manusia; sorting dan pembandingan rentang bekerja dengan benar sebagai pembandingan string biasa (pilihan paling umum)
julianday
julianday('2024-03-15') → 2460384.5 (desimal yang menghitung hari sejak zaman kuno)
Menghitung selisih dua tanggal dalam hari
unixepoch
strftime('%s', ...) → 1710460800 (integer detik sejak 1970-01-01)
Perhitungan waktu level detik / interoperabilitas antar sistem
Format apa pun yang kamu simpan, kamu bisa membacanya kembali sebagai 'YYYY-MM-DD' dengan date() atau sebagai 'YYYY-MM-DD HH:MM:SS' dengan datetime().
Kursus ini memakai string ISO secara default karena mudah dibaca manusia dan mudah dibandingkan, dan hanya mengonversi ke julianday / unixepoch saat diperlukan.
Tiga format penyimpanan tanggal2024-03-15 yang sama bisa disimpan dalam tiga format: string ISO, julianday, dan unixepoch. Ketiganya bisa dikonversi kembali ke bentuk yang bisa dibaca dengan date() / datetime(), dan string ISO membuat kamu bisa melakukan pembandingan rentang langsung sebagai pembandingan string.
-- Tanggal yang sama dalam 3 format (contoh read-only)SELECT'2024-03-15'AS iso_text, julianday('2024-03-15') AS as_julianday, strftime('%s','2024-03-15 00:00:00') AS as_unixepoch;-- Konversi masing-masing dari 3 format kembali ke tanggal yang bisa dibacaSELECTdate(julianday('2024-03-15')) AS from_jd,datetime(1710460800,'unixepoch') AS from_unix,date('2024-03-15') AS from_iso;-- Dengan string ISO, pembandingan rentang bekerja dengan benar sebagai pembandingan string biasaSELECT'2024-03-15'BETWEEN'2024-01-01'AND'2024-12-31'AS in_2024; -- 1
Misalkan kebutuhannya adalah: "Untuk satu penjualan di perf_sales, tampilkan tanggal penjualannya bersebelahan dalam format string ISO, julianday, dan unixepoch."
① Sempitkan perf_sales ke satu baris dengan sale_id = 12345 (karena tabelnya besar, selalu batasi ke satu baris).
② Baca sale_date dari baris itu apa adanya dengan alias iso.
③ Di sebelahnya, keluarkan julianday() yang diterapkan pada sale_date yang sama sebagai jd, dan strftime('%s', ...) sebagai unixep.
SQL Editor
Jalankan query untuk melihat hasil
Schema
Tidak ada tabel
Manipulasi dan agregasi tanggal dengan date() dan strftime()
date(nilai, modifier...): mengembalikan bagian tanggal sebagai 'YYYY-MM-DD', dan membuat kamu bisa melakukan perhitungan tanggal dengan modifier seperti '+1 month' / '-7 days' / 'start of month'
strftime(format, nilai): mengekstrak sebagian tanggal sebagai string memakai format specifier seperti %Y (tahun), %m (bulan), %d (hari), %w (hari dalam minggu)
Kombinasikan strftime('%Y', sale_date) dengan GROUP BY untuk mengagregasi berdasarkan tahun
Karena sale_date disimpan sebagai string ISO, kondisi rentang seperti `WHERE sale_date >= '2024-01-01'` bekerja dengan benar sebagai pembandingan string biasa
Apa yang dilakukan date() dan strftime()date() menangani aritmetika tanggal (tambah/kurang dengan modifier); strftime() menarik keluar satu bagian seperti tahun, bulan, atau hari dalam minggu. Dengan string ISO, kondisi rentang bekerja dengan benar sebagai pembandingan string biasa.
-- Manipulasi tanggal (contoh read-only)SELECTdate('2024-03-15','+1 month') AS plus_1_month, -- 2024-04-15date('2024-03-15','start of month') AS month_start, -- 2024-03-01 strftime('%Y', '2024-03-15') AS year_part, -- 2024 strftime('%Y-%m','2024-03-15') AS year_month; -- 2024-03-- Hitung berdasarkan tahun (string ISO, jadi ekstrak tahun dengan strftime dan GROUP BY)SELECT strftime('%Y', sale_date) AS yr, COUNT(*) AS cntFROM perf_salesGROUP BY yrORDER BY yr;
Misalkan kebutuhannya adalah: "Kelompokkan penjualan di perf_sales berdasarkan tahun dan tampilkan hitungan dan total amount untuk setiap tahun." Karena sale_date adalah string ISO, pakai strftime untuk mengekstrak tahun lalu agregasi.
① Ekstrak tahun dari sale_date dengan strftime('%Y', ...) dan beri alias yr.
② Keluarkan hitungan setiap tahun sebagai cnt, dan sum dari amount sebagai total.
③ Kelompokkan berdasarkan tahun (yr) dan urutkan hasilnya secara menaik berdasarkan tahun (selalu agregasi — tabelnya punya banyak baris).
SQL Editor
Jalankan query untuk melihat hasil
Schema
Tidak ada tabel
Misalkan kebutuhannya adalah: "Untuk Q1 2024 (1 Januari sampai 31 Maret) saja, tampilkan hitungan dan rata-rata amount." Karena sale_date adalah string ISO, kondisi rentang bekerja dengan benar sebagai pembandingan string biasa.
① Dari perf_sales, simpan hanya baris di mana sale_date berada di antara 2024-01-01 dan 2024-03-31 (inklusif).
② Keluarkan hitungan baris tersebut sebagai cnt dan rata-rata dari amount sebagai avg_amount.
③ Jangan kelompokkan — kembalikan satu baris agregat yang meliputi seluruh periode.
SQL Editor
Jalankan query untuk melihat hasil
Schema
Tidak ada tabel
Tabel STRICT — memberlakukan tipe ketat
Type affinity yang kita lihat sejauh ini mengonversi string yang terlihat seperti angka secara fleksibel.
Sebaliknya, ketika kamu menambahkan STRICT di akhir definisi tabel, tabel itu menolak menyimpan nilai yang tipenya tidak cocok dengan yang dideklarasikan.
Kalau kamu mencoba memasukkan string non-angka ke kolom numerik, nilainya tidak dikonversi secara implisit — kamu mendapat error.
Pakai ini untuk tabel di mana kamu ingin menangkap kekeliruan tipe sedini mungkin.
Di tabel STRICT, tipe kolom yang diizinkan terbatas pada INTEGER / REAL / TEXT / BLOB / ANY — INT dan nama tipe kustom tidak diizinkan.
Di latihan berikutnya kamu akan membuat sendiri tabel typed_strict dengan STRICT, dan di latihan-latihan setelahnya kamu akan memasukkan nilai yang cocok dan tidak cocok untuk melihat perbedaannya.
Pemeriksaan tipe di tabel STRICTTabel normal memakai type affinity dan mengonversi string yang terlihat seperti angka. Tabel STRICT tidak mengonversi nilai yang tidak cocok dengan tipe yang dideklarasikan dan menolak INSERT-nya sendiri dengan error.
-- Mendeklarasikan dan memakai tabel STRICT (contoh read-only)CREATETABLEIFNOTEXISTS typed_strict(a INTEGER, b TEXT, c REAL) STRICT;-- Baris dengan tipe yang cocok dimasukkan dengan baikINSERT INTO typed_strict VALUES (1, '2024-03-15', 1.5);-- Memasukkan string non-angka ke kolom a INTEGER-- tidak dikonversi secara implisit -- INSERT-nya error:-- cannot store TEXT value in INTEGER column typed_strict.aINSERT INTO typed_strict VALUES ('not-a-number', 'x', 1.0);
Misalkan kebutuhannya adalah: "Mendefinisikan tabel sendiri dengan STRICT supaya bisa memeriksa perilaku pemeriksaan tipe di latihan-latihan selanjutnya." Sebelum dua latihan berikutnya (di mana kamu akan memasukkan baris yang cocok dan tidak cocok), buat tabelnya sendiri di sini.
① Pertama jalankan DROP TABLE IF EXISTS typed_strict; untuk membersihkan versi sebelumnya, lalu CREATE tabel typed_strict dengan tiga kolom — a (INTEGER) / b (TEXT) / c (REAL) — menambahkan STRICT di akhir.
② Lalu jalankan PRAGMA table_info(typed_strict); untuk mengonfirmasi ketiga kolom didefinisikan sesuai deklarasi.
SQL Editor
Jalankan query untuk melihat hasil
Schema
Tidak ada tabel
Misalkan kebutuhannya adalah: "Tambahkan satu baris ke tabel typed_strict dari Latihan 4 dengan nilai yang cocok dengan tipe yang dideklarasikan setiap kolom, dan konfirmasi bahwa baris itu tersimpan."
① Masukkan satu baris ke typed_strict (a INTEGER / b TEXT / c REAL): integer di a, string tanggal format ISO di b, dan desimal di c. Kamu bisa memilih nilai sesukamu (misalnya pakai string seperti tanggal di b).
② Lalu jalankan SELECT * FROM typed_strict; untuk mengonfirmasi baris yang dimasukkan ada di sana.
SQL Editor
Jalankan query untuk melihat hasil
Schema
Tidak ada tabel
Mari cek apa yang terjadi ketika kamu mencoba memasukkan string non-angka ke kolom a (INTEGER) milik typed_strict. Tabel STRICT tidak mengonversi nilai yang tidak cocok — ia menolaknya, jadi INSERT ini akan error. Ini adalah latihan terakhir di artikel, dan intinya adalah merasakan error itu sendiri.
① Jalankan INSERT yang mencoba memasukkan string non-angka seperti 'not-a-number' ke kolom a milik typed_strict.
② Konfirmasi bahwa pesan error muncul (di konsol ini, mendapatkan error berarti kamu menjawab dengan benar).
SQL Editor
Jalankan query untuk melihat hasil
Schema
Tidak ada tabel
QUIZ
Cek Pemahaman
Jawab setiap pertanyaan satu per satu.
Soal 1Manakah yang merupakan keuntungan benar dari menyimpan tanggal sebagai string ISO seperti '2024-03-15'?
Soal 2Manakah yang dengan benar menggambarkan peran strftime('%Y', sale_date)?
Soal 3Manakah yang dengan benar menggambarkan apa yang terjadi ketika kamu mencoba INSERT string non-angka ke kolom INTEGER di tabel STRICT?