πŸ“Š Data Modelling
πŸŽ“ Pertemuan
Pertemuan 13: Dimensional Modelling: Snowflake & SCD

MODUL PERTEMUAN 13

DIMENSIONAL MODELLING: SNOWFLAKE SCHEMA & SLOWLY CHANGING DIMENSIONS


A. INFORMASI UMUM MATA KULIAH

ItemKeterangan
Mata KuliahData Modelling
Kode MKSSD1019
Bobot3 SKS (Praktikum)
Semester4 (Empat)
Program StudiSains Data
FakultasEkonomi dan Bisnis Islam
UniversitasUIN K.H. Abdurrahman Wahid Pekalongan
Dosen PengampuMohammad Reza Maulana, M.Kom

B. INFORMASI PERTEMUAN

B.1 Sub-CPMK Pertemuan 13

Sub-CPMK 4.1 dan 6.1: Mahasiswa mampu membandingkan star schema dan snowflake schema secara kritis untuk menentukan pilihan yang tepat sesuai konteks bisnis, serta mampu merancang dan mengimplementasikan strategi Slowly Changing Dimension (SCD Type 1, 2, dan 3) yang sesuai untuk setiap atribut dimensi β€” termasuk mengintegrasikan SCD Type 2 ke dalam star schema proyek kelompok yang telah dirancang di Pertemuan 12.

B.2 Tujuan Pembelajaran (Learning Objectives)

Setelah mengikuti pertemuan ini, mahasiswa akan mampu:

  1. Membandingkan star schema dan snowflake schema dari aspek struktur, performa query, storage, dan kemudahan pemeliharaan; serta menentukan kapan masing-masing lebih tepat dipilih berdasarkan karakteristik data dan kebutuhan bisnis (C5 - Mengevaluasi)
  2. Menjelaskan problem perubahan dimensi (Slowly Changing Dimension) dan mengapa ia menjadi tantangan fundamental dalam data warehouse (C2 - Memahami)
  3. Membedakan SCD Type 1, Type 2, dan Type 3 beserta implikasi masing-masing terhadap akurasi historis data (C2 - Memahami)
  4. Menentukan strategi SCD yang tepat untuk setiap atribut dalam sebuah dimensi berdasarkan kebutuhan bisnis (C5 - Mengevaluasi)
  5. Mengimplementasikan SCD Type 2 dalam SQL: prosedur insert awal, update saat perubahan, dan query historis yang memanfaatkan kolom berlaku_dari, berlaku_sampai, is_current (C3 - Menerapkan)
  6. Menerapkan best practices dimensional modelling sebagai panduan desain dari referensi tabel ringkasan yang disediakan (C3 - Menerapkan)

B.3 Kompetensi yang Dikembangkan

DomainKompetensi
KognitifMembandingkan dan mengevaluasi dua paradigma schema (C5); Menentukan strategi SCD yang tepat per atribut (C5); Mengimplementasikan SCD Type 2 (C3)
AfektifMembangun kesadaran bahwa "data berubah seiring waktu" adalah realitas bisnis yang harus diantisipasi sejak awal desain, bukan sebagai masalah yang ditangani belakangan; menghargai pentingnya mempertahankan riwayat data untuk keakuratan analitik
PsikomotorikMenulis SQL prosedur SCD Type 2 (UPDATE + INSERT) yang benar; mengidentifikasi atribut mana dalam dimensi yang memerlukan strategi SCD berbeda

B.4 Indikator Pencapaian

Setelah mengikuti pertemuan ini, mahasiswa diharapkan mampu:

  1. Menggambar diagram snowflake schema dari star schema yang sudah ada dengan benar
  2. Menjelaskan minimal 4 trade-off konkret antara star dan snowflake dengan contoh nyata
  3. Diberikan daftar atribut dimensi, menentukan SCD Type yang tepat (1, 2, atau 3) untuk setiap atribut beserta alasannya
  4. Menulis SQL SCD Type 2 yang lengkap: INSERT awal, UPDATE saat perubahan, dan 3 jenis query historis
  5. Memperbarui star schema proyek kelompok dengan strategi SCD yang eksplisit per atribut

B.5 Alokasi Waktu

NoKegiatanDurasiKeterangan
1Pembukaan & Review Singkat P125 menitJembatan dari star schema
2Aktivitas Pemantik: "Data Berubah - Bagaimana Sikapmu?"10 menitMembangun intuisi SCD
3Materi 1: Snowflake Schema + Star vs Snowflake25 menitCeramah + diagram perbandingan + decision matrix (handout)
4Break10 menit-
5Materi 2: Problem SCD - Mengapa Dimensi Berubah Itu Rumit10 menitMembangun konteks
6Materi 3: SCD Type 1 - Timpa, Lupakan Sejarah8 menitCeramah + SQL
7Materi 4: SCD Type 2 - Rekam Sejarah Lengkap35 menitCeramah + SQL mendalam + latihan INSERT/UPDATE/query historis
8Materi 5: SCD Type 3 - Sejarah Terbatas10 menitCeramah + SQL
9Materi 6: SCD Type 4 & 6 (Hybrid) + Decision Matrix5 menitRingkasan singkat - referensi tabel
10Materi 7: Best Practices (Tabel Referensi)5 menitDibagikan sebagai handout/lampiran, dipresentasikan ringkas
11Praktikum: Update Star Schema P12 dengan Strategi SCD12 menitIndividu
12Kuis Penutup & Briefing Review Menuju P14-P1510 menit-
Total145 menit(termasuk break)

C. MATERI PEMBELAJARAN

C.1 Jembatan dari Pertemuan 12

Recap (5 menit): Di Pertemuan 12, kita menguasai fondasi star schema: empat langkah Kimball, grain, tiga jenis measures, surrogate key, dan dimensi yang wide dan denormalized. Kita juga sudah menyisipkan kolom misterius di DDL dimensi:

-- Dari DDL P12 β€” kolom yang belum dijelaskan penuh:
berlaku_dari    DATE    NOT NULL,
berlaku_sampai  DATE    NOT NULL DEFAULT '9999-12-31',
is_current      TINYINT(1) NOT NULL DEFAULT 1,

"Tiga kolom ini adalah benang merah ke Pertemuan 13. Mereka adalah jimat yang melindungi akurasi analitik historis kamu. Hari ini kita aktivasi fungsinya."

APA YANG SUDAH KITA KUASAI (P12):
  βœ“ Kimball Four-Step Process
  βœ“ Grain β€” keputusan paling fundamental
  βœ“ Additive / semi-additive / non-additive measures
  βœ“ Tabel dimensi: wide, denormalized, surrogate key
  βœ“ dim_waktu dan cara populate-nya
  βœ“ Variasi dimensi khusus (conformed, role-playing, junk, degenerate)
  βœ“ Star schema DDL dan query analitik

PERTANYAAN YANG BELUM TERJAWAB SEPENUHNYA:
  βœ— Apakah dimensi selalu harus di-denormalize?
    β†’ Kapan normalisasi dimensi (snowflake) lebih masuk akal?
  βœ— Kolom berlaku_dari, berlaku_sampai, is_current β€” bagaimana cara kerjanya?
    β†’ Apa yang terjadi saat atribut dimensi berubah di dunia nyata?
  βœ— Strategi apa yang tepat untuk menangani perubahan dimensi yang berbeda-beda?

β†’ Itulah fokus Pertemuan 13!

C.2 Aktivitas Pemantik β€” "Data Berubah: Bagaimana Sikapmu?"

Instruksi (10 menit): Dosen menyajikan tiga skenario perubahan data. Mahasiswa mendiskusikan secara berpasangan: "Apakah riwayat sebelumnya perlu disimpan? Mengapa? Apa dampaknya terhadap analitik?"

Skenario 1 β€” Kesalahan Input

Seorang data entry staff salah mengetik nama pelanggan:
  Sebelum  : "Budhi Santosa"
  Sesudah  : "Budi Santoso"  (koreksi typo)

Pertanyaan:
β†’ Apakah kita perlu menyimpan versi "Budhi Santosa" sebagai riwayat?
β†’ Atau cukup ditimpa dengan yang benar?

Skenario 2 β€” Perubahan Bisnis Nyata

Pelanggan "Siti Rahayu" pindah kota:
  Sebelum  : kota = "Semarang"   (berlaku Jan 2021 – Des 2023)
  Sesudah  : kota = "Jakarta"    (berlaku Jan 2024 – sekarang)

Pertanyaan:
β†’ Jika kita timpa saja: laporan "Revenue dari Semarang tahun 2022"
  apakah masih akurat? Atau Siti sekarang "dianggap" sudah di Jakarta di 2022?
β†’ Apa dampaknya terhadap laporan ekspansi kota yang sudah dibuat tahun 2022?

Skenario 3 β€” Restrukturisasi Organisasi

Produk "Batik Tulis Pekalongan Premium" berpindah kategori:
  Sebelum  : kategori = "Batik Tulis"      (2021–2023)
  Sesudah  : kategori = "Koleksi Premium"  (2024–sekarang)

Pertanyaan:
β†’ Jika manajer minta laporan: "Revenue dari kategori Batik Tulis tahun 2022",
  apakah produk ini seharusnya masuk ke sana?
β†’ Bagaimana agar analisis tren per kategori tidak menjadi misleading?

Insight yang Dosen Ungkap:

Tiga skenario ini memerlukan jawaban yang BERBEDA:

  • Skenario 1: timpa saja β€” itu kesalahan, bukan perubahan bisnis
  • Skenario 2: harus simpan riwayat β€” pindah kota adalah fakta bisnis yang valid
  • Skenario 3: tergantung kebijakan β€” tapi menyimpan riwayat jauh lebih aman

"Bagaimana kita menangani perubahan ini secara sistematis di data warehouse adalah inti dari konsep Slowly Changing Dimension (SCD). Tapi sebelum masuk ke SCD, ada satu topik arsitektur yang harus kita bahas terlebih dahulu: snowflake schema."


C.3 Materi 1: Snowflake Schema β€” Normalisasi Dimensi

C.3.1 Definisi dan Konsep Dasar

SNOWFLAKE SCHEMA adalah perluasan (extension) dari star schema
di mana tabel dimensi DINORMALISASI β€” hierarki di dalam dimensi
dipecah menjadi tabel-tabel sub-dimensi tersendiri.

Disebut "snowflake" karena bentuk diagramnya menyerupai kepingan
salju β€” satu pusat (tabel fakta) dengan cabang yang semakin
memanjang dan bercabang (dimensi β†’ sub-dimensi β†’ sub-sub-dimensi).

C.3.2 Dari Star ke Snowflake β€” Transformasi Visual

STAR SCHEMA β€” dim_produk denormalized:

             fakta_penjualan
                   β”‚
                   β”‚  FK
                   β–Ό
           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
           β”‚          dim_produk               β”‚
           β”‚ kunci_produk        (PK)          β”‚
           β”‚ id_produk_src                     β”‚
           β”‚ nama_produk                       β”‚
           β”‚ subkategori         ◄──── semua   β”‚
           β”‚ kategori            ◄──── dalam   β”‚
           β”‚ kelompok_kategori   ◄──── satu    β”‚
           β”‚ nama_supplier       ◄──── tabel!  β”‚
           β”‚ kota_supplier                     β”‚
           β”‚ teknik_pembuatan                  β”‚
           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

SNOWFLAKE SCHEMA β€” dim_produk dinormalisasi:

             fakta_penjualan
                   β”‚
                   β”‚  FK
                   β–Ό
           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
           β”‚   dim_produk    β”‚
           β”‚ kunci_produk PK β”‚
           β”‚ nama_produk     β”‚
           β”‚ kunci_subkat FK β”‚β”€β”€β–Ίβ”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
           β”‚ kunci_supplier FKβ”‚   β”‚  dim_subkategori  β”‚
           β”‚ teknik_pembuatanβ”‚   β”‚ kunci_subkat    PKβ”‚
           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚ nama_subkategori  β”‚
                                 β”‚ kunci_kategori FK β”‚β”€β”€β–Ίβ”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚  dim_kategori     β”‚
                                                         β”‚ kunci_kategori PK β”‚
                             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”‚ nama_kategori     β”‚
                             β”‚ dim_supplier  β”‚            β”‚ kunci_kelompok FK β”‚β”€β”€β–Ίβ”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                             β”‚ kunci_sup  PK β”‚            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚ dim_kelompok   β”‚
                             β”‚ nama_supplier β”‚                                    β”‚ kunci_kel   PK β”‚
                             β”‚ kota_supplier β”‚                                    β”‚ nama_kelompok  β”‚
                             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Struktur "snowflake" terlihat jelas:
fakta β†’ dim_produk β†’ dim_subkategori β†’ dim_kategori β†’ dim_kelompok
                   β†’ dim_supplier

C.3.3 DDL Snowflake Schema β€” Hierarki Produk

-- ============================================================
-- SNOWFLAKE SCHEMA β€” Hierarki Kategori Produk
-- Perhatikan: setiap level hierarki jadi tabel tersendiri
-- ============================================================
 
-- Level 3: Kelompok Kategori (paling tinggi)
CREATE TABLE dim_kelompok_kategori (
    kunci_kelompok   TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
    nama_kelompok    VARCHAR(100)     NOT NULL,
    deskripsi        VARCHAR(300)     NULL,
    CONSTRAINT pk_dim_kelompok PRIMARY KEY (kunci_kelompok)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-- Level 2: Kategori
CREATE TABLE dim_kategori (
    kunci_kategori   SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
    kunci_kelompok   TINYINT UNSIGNED  NOT NULL,            -- FK ke level atas
    nama_kategori    VARCHAR(100)      NOT NULL,
    deskripsi        VARCHAR(300)      NULL,
    CONSTRAINT pk_dim_kategori PRIMARY KEY (kunci_kategori),
    CONSTRAINT fk_kat_kelompok
        FOREIGN KEY (kunci_kelompok)
        REFERENCES dim_kelompok_kategori (kunci_kelompok)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-- Level 1: Sub-kategori
CREATE TABLE dim_subkategori (
    kunci_subkategori SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
    kunci_kategori    SMALLINT UNSIGNED NOT NULL,           -- FK ke level atas
    nama_subkategori  VARCHAR(100)      NOT NULL,
    CONSTRAINT pk_dim_subkat PRIMARY KEY (kunci_subkategori),
    CONSTRAINT fk_subkat_kategori
        FOREIGN KEY (kunci_kategori)
        REFERENCES dim_kategori (kunci_kategori)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-- Supplier (dimensi terpisah karena bukan hierarki produk)
CREATE TABLE dim_supplier (
    kunci_supplier   SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
    nama_supplier    VARCHAR(150)      NOT NULL,
    kota_supplier    VARCHAR(100)      NOT NULL,
    provinsi         VARCHAR(100)      NOT NULL,
    CONSTRAINT pk_dim_supplier PRIMARY KEY (kunci_supplier)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-- dim_produk (SNOWFLAKE VERSION) β€” lebih ramping, tapi punya banyak FK
CREATE TABLE dim_produk_snowflake (
    kunci_produk       INT UNSIGNED      NOT NULL AUTO_INCREMENT,
    id_produk_src      INT UNSIGNED      NOT NULL,
    nama_produk        VARCHAR(200)      NOT NULL,
    kunci_subkategori  SMALLINT UNSIGNED NOT NULL,  -- FK ke dim_subkategori
    kunci_supplier     SMALLINT UNSIGNED NOT NULL,  -- FK ke dim_supplier
    harga_jual         DECIMAL(15,2)     NOT NULL,
    teknik_pembuatan   VARCHAR(50)       NULL,
    bahan_utama        VARCHAR(100)      NULL,
    motif              VARCHAR(100)      NULL,
    berlaku_dari       DATE              NOT NULL,
    berlaku_sampai     DATE              NOT NULL DEFAULT '9999-12-31',
    is_current         TINYINT(1)        NOT NULL DEFAULT 1,
    CONSTRAINT pk_dim_produk_sf PRIMARY KEY (kunci_produk),
    CONSTRAINT fk_prod_subkat
        FOREIGN KEY (kunci_subkategori)
        REFERENCES dim_subkategori (kunci_subkategori),
    CONSTRAINT fk_prod_supplier
        FOREIGN KEY (kunci_supplier)
        REFERENCES dim_supplier (kunci_supplier)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-- ──────────────────────────────────────────────────────────────
-- DAMPAK KE QUERY β€” perhatikan perbedaan jumlah JOIN!
-- ──────────────────────────────────────────────────────────────
 
-- STAR SCHEMA (dim_produk denormalized):
-- Revenue per kategori β€” hanya butuh 2 JOIN
SELECT p.kategori, SUM(f.revenue_bersih) AS total_revenue
FROM fakta_penjualan f
JOIN dim_produk p ON f.kunci_produk = p.kunci_produk
JOIN dim_waktu  w ON f.kunci_waktu  = w.kunci_waktu
WHERE w.tahun = 2024
GROUP BY p.kategori;
 
-- SNOWFLAKE SCHEMA (dim_produk_snowflake):
-- Revenue per kategori β€” butuh 4 JOIN
SELECT k.nama_kategori, SUM(f.revenue_bersih) AS total_revenue
FROM fakta_penjualan f
JOIN dim_produk_snowflake p  ON f.kunci_produk       = p.kunci_produk
JOIN dim_subkategori      sk ON p.kunci_subkategori   = sk.kunci_subkategori
JOIN dim_kategori          k ON sk.kunci_kategori     = k.kunci_kategori
JOIN dim_waktu             w ON f.kunci_waktu         = w.kunci_waktu
WHERE w.tahun = 2024
GROUP BY k.nama_kategori;
-- β†’ Query lebih kompleks, JOIN lebih banyak, risiko lebih tinggi

C.4 Materi 2: Star vs Snowflake β€” Kapan Memilih Mana?

C.4.1 Perbandingan Komprehensif

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Dimensi Perbandingan     β”‚ STAR SCHEMA                   β”‚ SNOWFLAKE SCHEMA              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ STRUKTUR DIMENSI         β”‚ Denormalized (1 tabel per     β”‚ Normalized (banyak tabel      β”‚
β”‚                          β”‚ dimensi, semua atribut flat)  β”‚ per hierarki dimensi)         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ JUMLAH JOIN PER QUERY    β”‚ Sedikit: 1 hop fact β†’ dim    β”‚ Banyak: fact β†’ dim β†’ sub-dim β”‚
β”‚                          β”‚ (mudah diprediksi dan debug)  β”‚ (bertambah setiap level)      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ PERFORMA QUERY           β”‚ βœ“ Lebih cepat                 β”‚ βœ— Lebih lambat (lebih JOIN)  β”‚
β”‚ (SELECT analitik)        β”‚ Optimizer mudah memprediksi   β”‚ Lebih banyak intermediate     β”‚
β”‚                          β”‚ join plan                     β”‚ result set                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ REDUNDANSI STORAGE       β”‚ βœ— Lebih besar                 β”‚ βœ“ Lebih kecil                 β”‚
β”‚                          β”‚ (nama kategori diulang di     β”‚ (nama kategori 1x di tabel    β”‚
β”‚                          β”‚ setiap baris dim_produk)      β”‚ dim_kategori)                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ PEMELIHARAAN DIMENSI     β”‚ βœ— Agak lebih sulit            β”‚ βœ“ Lebih mudah                 β”‚
β”‚ (UPDATE nama kategori)   β”‚ Harus UPDATE banyak baris di  β”‚ UPDATE 1 baris di dim_kategoriβ”‚
β”‚                          β”‚ dim_produk                    β”‚ β†’ otomatis berlaku semua      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ KEMUDAHAN DIPAHAMI       β”‚ βœ“ Intuitif                    β”‚ βœ— Lebih kompleks              β”‚
β”‚ oleh Business User       β”‚ Analyst/manajer mudah         β”‚ Lebih sulit dipahami tanpa    β”‚
β”‚                          β”‚ memahami struktur             β”‚ dokumentasi skema             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ KOMPATIBILITAS BI TOOLS  β”‚ βœ“ Sangat baik                 β”‚ βœ— Kurang baik                 β”‚
β”‚ (Tableau, Power BI, dll) β”‚ Sebagian besar BI tools       β”‚ Banyak BI tools kesulitan     β”‚
β”‚                          β”‚ dirancang untuk star schema   β”‚ handle multi-level join       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ KONSISTENSI NILAI        β”‚ βœ— Risiko inkonsistensi        β”‚ βœ“ Konsistensi terjamin        β”‚
β”‚ DIMENSI                  β”‚ Update nama kategori harus    β”‚ Satu sumber kebenaran untuk   β”‚
β”‚                          β”‚ ke banyak baris (error-prone) β”‚ setiap nilai dimensi          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ KONTEKS PENGGUNAAN       β”‚ Default untuk hampir semua    β”‚ Gunakan hanya jika ada alasan β”‚
β”‚ YANG DIREKOMENDASIKAN    β”‚ proyek data warehouse         β”‚ spesifik yang kuat            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

C.4.2 Decision Framework: Pilih Star atau Snowflake?

PANDUAN PENGAMBILAN KEPUTUSAN:

Mulai dari pertanyaan ini:

1. Apakah storage adalah kendala serius?
   TIDAK β†’ Pilih STAR (performa lebih penting dari storage di DW modern)
   YA    β†’ Pertimbangkan snowflake untuk dimensi yang sangat besar

2. Apakah dimensi memiliki hierarki yang SANGAT dalam (4+ level)?
   TIDAK β†’ Pilih STAR (flatten saja)
   YA    β†’ Snowflake bisa dipertimbangkan untuk hierarki tersebut saja

3. Apakah nilai di level hierarki berubah sangat sering?
   TIDAK β†’ STAR (denormalized, SCD handle perubahan)
   YA    β†’ Snowflake memudahkan UPDATE satu baris di sub-dimensi

4. Apakah BI tools yang digunakan mendukung snowflake dengan baik?
   YA    β†’ Snowflake bisa dipertimbangkan
   TIDAK β†’ Wajib STAR

5. Apakah tim analyst/end-user teknis dan bisa handle JOIN kompleks?
   YA    β†’ Snowflake lebih fleksibel
   TIDAK β†’ STAR lebih ramah pengguna

KESIMPULAN PRAKTIS:
  β†’ STAR adalah pilihan default yang tepat untuk 90% kasus
  β†’ Snowflake yang PENUH (seluruh dimensi dinormalisasi)
    sangat jarang digunakan di industri nyata
  β†’ Solusi HYBRID yang paling umum: star schema dengan sebagian
    kecil dimensi yang memiliki hierarki sangat dalam di-normalize
    (sering disebut "star with normalized sub-dimensions")

C.4.3 Solusi Hybrid β€” Yang Paling Banyak Digunakan di Industri

HYBRID APPROACH: Gabungkan yang terbaik dari keduanya

Prinsip: Gunakan star untuk sebagian besar dimensi, gunakan
         normalisasi parsial HANYA untuk hierarki yang memiliki
         alasan kuat (biasanya: hierarki lokasi geografis yang
         sangat dalam atau hierarki produk yang kompleks)

CONTOH NYATA β€” DW Toko Batik Online Hybrid:

  fakta_penjualan
       β”‚
       β”œβ”€β”€β–Ί dim_waktu          (FLAT/DENORM β€” star style)
       β”œβ”€β”€β–Ί dim_pelanggan      (FLAT/DENORM β€” star style)
       β”œβ”€β”€β–Ί dim_produk         (FLAT/DENORM β€” star style, include subkat & kat)
       β”œβ”€β”€β–Ί dim_kanal          (FLAT/DENORM β€” star style)
       └──► dim_lokasi_kirim   (PARTIAL SNOWFLAKE)
                β”‚
                └──► dim_wilayah_indonesia  ← tabel referensi provinsi
                                              (karena ada 38 provinsi,
                                               lebih efisien normalize)

  Catatan: dim_lokasi_kirim tetap menyimpan nama_provinsi secara flat
           untuk performa query, dim_wilayah_indonesia digunakan
           sebagai lookup master untuk validasi ETL, bukan untuk JOIN
           di setiap query analitik

C.5 Materi 3: Problem SCD β€” Mengapa Perubahan Dimensi Itu Rumit

C.5.1 Skenario Nyata yang Memecahkan Analitik

Kembali ke skenario pemantik β€” sekarang kita analisis lebih dalam mengapa perubahan dimensi bisa menghancurkan keakuratan laporan.

SKENARIO TANPA PENANGANAN SCD:

Kondisi awal (Maret 2022):
  dim_pelanggan:
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ kunci_pelanggan  β”‚ nama         β”‚ kota         β”‚ segmen    β”‚
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚ 1001             β”‚ Siti Rahayu  β”‚ Semarang     β”‚ Gold      β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

  fakta_penjualan (rekaman 2022):
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ kunci_waktuβ”‚ kunci_pelanggan β”‚ revenue_bersih       β”‚
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚ 20220315   β”‚ 1001            β”‚ 850.000              β”‚  ← beli di Semarang
  β”‚ 20220620   β”‚ 1001            β”‚ 1.200.000            β”‚  ← beli di Semarang
  β”‚ 20220918   β”‚ 1001            β”‚ 670.000              β”‚  ← beli di Semarang
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Januari 2024: Siti pindah ke Jakarta β†’ Tim ETL melakukan:
  UPDATE dim_pelanggan SET kota = 'Jakarta' WHERE kunci_pelanggan = 1001;

Sekarang, laporan 2022 yang lama menghasilkan:

  SELECT pel.kota, SUM(f.revenue_bersih) AS revenue_2022
  FROM fakta_penjualan f
  JOIN dim_pelanggan pel ON f.kunci_pelanggan = pel.kunci_pelanggan
  JOIN dim_waktu     w   ON f.kunci_waktu     = w.kunci_waktu
  WHERE w.tahun = 2022
  GROUP BY pel.kota;

  HASIL YANG SALAH:
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ kota     β”‚ revenue_2022 β”‚
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚ Jakarta  β”‚ 2.720.000    β”‚ ← SALAH! Siti di 2022 masih di Semarang!
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

  DAMPAK BISNIS:
  β†’ Laporan ekspansi Semarang tahun 2022 kini menunjukkan revenue yang
    lebih rendah (underestimated)
  β†’ Laporan Jakarta 2022 lebih tinggi dari seharusnya (overestimated)
  β†’ Keputusan strategis (buka cabang, alokasi budget) bisa salah!
  β†’ Jika laporan sudah di-print dan diserahkan ke direksi, kini
    angkanya berbeda β†’ hilang kepercayaan terhadap data warehouse

Kesimpulan: Perubahan dimensi adalah realitas bisnis yang tidak bisa dihindari. Yang bisa kita kendalikan adalah BAGAIMANA kita merespons perubahan itu di data warehouse. Kimball menyebut strategi-strategi ini sebagai Slowly Changing Dimensions.

C.5.2 Mengapa Disebut "Slowly Changing"?

"Slowly" bukan berarti lambat dalam arti waktu β€” melainkan merujuk
pada fakta bahwa perubahan dimensi terjadi JARANG dibandingkan
dengan frekuensi munculnya data fakta baru.

  fakta_penjualan: ribuan baris baru per hari  β†’ FAST changing
  dim_pelanggan: beberapa baris berubah per bulan β†’ SLOWLY changing

SCD adalah teknik untuk menangani perubahan yang "lambat" itu
agar tidak merusak integritas historis data warehouse.

VARIABEL YANG BERUBAH DI DIMENSI:
  Pelanggan: pindah kota, naik segmen, ganti nama setelah menikah
  Produk: berganti kategori, harga berubah, supplier berganti
  Karyawan: naik jabatan, pindah divisi, resign dan kembali
  Lokasi: bergabung dengan kecamatan lain, kode pos berubah

C.6 Materi 4: SCD Type 1 β€” Timpa, Lupakan Sejarah

C.6.1 Mekanisme SCD Type 1

SCD TYPE 1 β€” OVERWRITE (Timpa)
  Strategi paling sederhana: UPDATE nilai lama dengan nilai baru.
  Riwayat lama TIDAK disimpan sama sekali.

KAPAN DIGUNAKAN:
  βœ“ Koreksi kesalahan data (typo, salah input) β†’ sejarah yang
    salah tidak perlu disimpan, justru harus dihapus
  βœ“ Atribut yang tidak memiliki nilai historis bisnis
    (mis: nomor telepon β€” analitik jarang butuh "HP lama")
  βœ“ Ketika kebijakan bisnis menyatakan "yang berlaku = yang terkini"
  βœ— JANGAN gunakan untuk atribut yang mempengaruhi analisis historis
    (mis: kota, segmen, kategori produk)

SEBELUM (Typo pada nama):
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ kunci_pelanggan β”‚ nama          β”‚ kota     β”‚ no_telepon      β”‚
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚ 1001            β”‚ Budhi Santosa β”‚ Semarang β”‚ 081234567890    β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

SESUDAH TYPE 1 (Koreksi typo):
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ kunci_pelanggan β”‚ nama          β”‚ kota     β”‚ no_telepon      β”‚
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚ 1001            β”‚ Budi Santoso  β”‚ Semarang β”‚ 081234567890    β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  Surrogate key TETAP SAMA β†’ tidak ada baris baru β†’ tidak ada FK yang berubah

C.6.2 Implementasi SQL β€” SCD Type 1

-- ============================================================
-- SCD TYPE 1 β€” Simple UPDATE
-- ============================================================
 
-- Kasus 1: Koreksi typo nama pelanggan
UPDATE dim_pelanggan
SET nama_lengkap = 'Budi Santoso'
WHERE id_pelanggan_src = 501
  AND is_current = 1;
 
-- Kasus 2: Update nomor telepon (informasi yang tidak perlu disimpan historis)
UPDATE dim_pelanggan
SET no_telepon = '082198765432'
WHERE id_pelanggan_src = 501
  AND is_current = 1;
 
-- Kasus 3: Koreksi kategori produk yang salah input
UPDATE dim_produk
SET kategori = 'Batik Cap',
    subkategori = 'Batik Cap Kontemporer'
WHERE id_produk_src = 1023
  AND is_current = 1;
 
-- Verifikasi setelah update (tidak ada versi lama yang tertinggal)
SELECT kunci_pelanggan, nama_lengkap, kota, is_current
FROM dim_pelanggan
WHERE id_pelanggan_src = 501;
-- Hasil: 1 baris saja, dengan nilai yang sudah di-update
 
-- DAMPAK KE TABEL FAKTA:
-- Tidak ada yang perlu diubah di fakta!
-- Semua FK di fakta tetap menunjuk ke kunci yang sama (1001),
-- yang sekarang punya nilai baru.
-- Konsekuensi: riwayat lama pun "berubah" ikut nilai baru.
-- Ini disengaja untuk Type 1.

C.7 Materi 5: SCD Type 2 β€” Rekam Sejarah Lengkap

SCD Type 2 adalah strategi yang paling umum, paling powerful, dan paling sering digunakan di data warehouse produksi. Ia memungkinkan analitik historis yang akurat dengan cara menyimpan setiap versi perubahan sebagai baris baru.

C.7.1 Mekanisme SCD Type 2

SCD TYPE 2 β€” ADD NEW ROW (Tambah Baris Baru)
  Setiap kali ada perubahan pada atribut yang dilacak:
  1. Baris lama "DITUTUP" β†’ berlaku_sampai diisi tanggal kemarin,
                             is_current diubah menjadi 0
  2. Baris baru "DIBUKA"  β†’ berlaku_dari diisi tanggal hari ini,
                             berlaku_sampai = '9999-12-31',
                             is_current = 1
  3. Surrogate key BARU digenerate untuk baris baru
  4. FK di tabel fakta ke depan akan merujuk ke surrogate key BARU

KAPAN DIGUNAKAN:
  βœ“ Atribut yang berubah dan perubahan itu punya makna historis
    β†’ kota pelanggan, segmen pelanggan, kategori produk,
      jabatan karyawan, harga produk (dalam konteks tertentu)
  βœ“ Ketika bisnis butuh menjawab: "Bagaimana kondisi X PADA SAAT
    kejadian ini terjadi?" (point-in-time analysis)
  βœ“ Ketika laporan historis harus tetap akurat meskipun data berubah

C.7.2 Ilustrasi Detail SCD Type 2

KONDISI AWAL (Januari 2022 β€” Siti mendaftar):
  dim_pelanggan:
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ kunci_pelβ”‚ id_pel_src β”‚ nama         β”‚ kota     β”‚ berlaku_dari  β”‚ berlaku_sampaiβ”‚ is_currentβ”‚
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚ 1001     β”‚ 501        β”‚ Siti Rahayu  β”‚ Semarang β”‚ 2022-01-15    β”‚ 9999-12-31    β”‚ 1        β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

  fakta_penjualan (2022–2023): semua baris FK kunci_pelanggan = 1001

───────────────────────────────────────────────────────────────────

PERUBAHAN (2 Januari 2024 β€” Siti pindah ke Jakarta):

  LANGKAH 1: Tutup baris lama
  UPDATE dim_pelanggan
  SET berlaku_sampai = '2024-01-01',
      is_current     = 0
  WHERE id_pelanggan_src = 501
    AND is_current = 1;

  LANGKAH 2: Insert baris baru (surrogate key baru!)
  INSERT INTO dim_pelanggan (id_pelanggan_src, nama, kota, berlaku_dari)
  VALUES (501, 'Siti Rahayu', 'Jakarta', '2024-01-02');

  dim_pelanggan SEKARANG (dua baris!):
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ kunci_pelβ”‚ id_pel_src β”‚ nama         β”‚ kota     β”‚ berlaku_dari  β”‚ berlaku_sampaiβ”‚ is_currentβ”‚
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚ 1001     β”‚ 501        β”‚ Siti Rahayu  β”‚ Semarang β”‚ 2022-01-15    β”‚ 2024-01-01    β”‚ 0        β”‚ ← tertutup
  β”‚ 2847     β”‚ 501        β”‚ Siti Rahayu  β”‚ Jakarta  β”‚ 2024-01-02    β”‚ 9999-12-31    β”‚ 1        β”‚ ← aktif
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

  fakta_penjualan:
  - Baris 2022–2023: masih FK ke kunci_pelanggan = 1001 (Semarang!) ← TIDAK BERUBAH
  - Baris 2024+:     FK ke kunci_pelanggan = 2847 (Jakarta!) ← BARU via ETL

───────────────────────────────────────────────────────────────────

HASIL QUERY 2022 SEKARANG:

  SELECT pel.kota, SUM(f.revenue_bersih) AS revenue_2022
  FROM fakta_penjualan f
  JOIN dim_pelanggan pel ON f.kunci_pelanggan = pel.kunci_pelanggan
  JOIN dim_waktu     w   ON f.kunci_waktu     = w.kunci_waktu
  WHERE w.tahun = 2022
  GROUP BY pel.kota;

  HASIL YANG BENAR:
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ kota     β”‚ revenue_2022 β”‚
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚ Semarang β”‚ 2.720.000    β”‚ ← BENAR! Siti di 2022 memang di Semarang
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  β†’ Jakarta tidak muncul karena tidak ada transaksi 2022 dari pelanggan
    yang pada saat itu berada di Jakarta.

C.7.3 Implementasi SQL Lengkap β€” SCD Type 2

-- ============================================================
-- SCD TYPE 2 β€” Implementasi Lengkap dengan Stored Procedure
-- Domain: dim_pelanggan β€” Toko Batik Online DW
-- ============================================================
 
-- ──────────────────────────────────────────────────────────────
-- TAHAP 1: INSERT AWAL (saat data pertama kali masuk ke DW)
-- ──────────────────────────────────────────────────────────────
INSERT INTO dim_pelanggan (
    id_pelanggan_src,
    nama_lengkap,
    jenis_kelamin,
    kelompok_usia,
    kota,
    kabupaten_kota,
    provinsi,
    pulau,
    wilayah,
    tgl_daftar,
    tahun_daftar,
    segmen_pelanggan,
    berlaku_dari,
    berlaku_sampai,
    is_current
) VALUES (
    501,                      -- id dari OLTP
    'Siti Rahayu',
    'P',
    'Dewasa Muda',
    'Semarang',
    'Kota Semarang',
    'Jawa Tengah',
    'Jawa',
    'Jawa Tengah & DIY',
    '2022-01-15',
    2022,
    'Baru',
    '2022-01-15',             -- berlaku_dari = tanggal pertama kali masuk DW
    '9999-12-31',             -- berlaku_sampai = "tak terbatas"
    1                         -- is_current = 1 (aktif)
);
 
-- ──────────────────────────────────────────────────────────────
-- TAHAP 2: PROSES UPDATE SCD TYPE 2
-- (dijalankan setiap kali ETL mendeteksi perubahan atribut)
-- ──────────────────────────────────────────────────────────────
 
-- Step A: Tutup record lama (jangan DELETE β€” hanya ubah tanggal akhir)
UPDATE dim_pelanggan
SET berlaku_sampai  = DATE_SUB(CURDATE(), INTERVAL 1 DAY),  -- kemarin
    is_current      = 0
WHERE id_pelanggan_src = 501
  AND is_current = 1;
 
-- Step B: Insert record baru dengan nilai baru dan surrogate key baru
INSERT INTO dim_pelanggan (
    id_pelanggan_src,
    nama_lengkap,
    jenis_kelamin,
    kelompok_usia,
    kota,
    kabupaten_kota,
    provinsi,
    pulau,
    wilayah,
    tgl_daftar,
    tahun_daftar,
    segmen_pelanggan,
    berlaku_dari,
    berlaku_sampai,
    is_current
)
-- Ambil semua atribut dari record lama, tapi ganti kota (dan nilai terkait)
SELECT
    id_pelanggan_src,
    nama_lengkap,
    jenis_kelamin,
    kelompok_usia,
    'Jakarta',              -- ← nilai baru: kota berubah
    'Kota Jakarta Pusat',   -- ← nilai baru: kabupaten_kota berubah
    'DKI Jakarta',          -- ← nilai baru: provinsi berubah
    'Jawa',                 -- sama
    'Jabodetabek',          -- ← nilai baru: wilayah berubah
    tgl_daftar,
    tahun_daftar,
    'Gold',                 -- ← nilai baru: segmen naik (bisa SCD 2 atau 1 tergantung kebijakan)
    CURDATE(),              -- berlaku_dari = hari ini
    '9999-12-31',
    1
FROM dim_pelanggan
WHERE id_pelanggan_src = 501
  AND is_current = 0        -- ambil dari record yang baru saja ditutup
  AND berlaku_sampai = DATE_SUB(CURDATE(), INTERVAL 1 DAY)
LIMIT 1;
 
-- ──────────────────────────────────────────────────────────────
-- STORED PROCEDURE β€” Wrapper untuk proses SCD Type 2
-- ──────────────────────────────────────────────────────────────
DELIMITER //
CREATE PROCEDURE upsert_pelanggan_scd2(
    IN p_id_src         INT UNSIGNED,
    IN p_nama           VARCHAR(150),
    IN p_kota           VARCHAR(100),
    IN p_kabkota        VARCHAR(100),
    IN p_provinsi       VARCHAR(100),
    IN p_pulau          VARCHAR(50),
    IN p_wilayah        VARCHAR(50),
    IN p_segmen         VARCHAR(30),
    IN p_tgl_efektif    DATE
)
BEGIN
    DECLARE v_exists INT DEFAULT 0;
    DECLARE v_changed INT DEFAULT 0;
 
    -- Cek apakah record sudah ada
    SELECT COUNT(*) INTO v_exists
    FROM dim_pelanggan
    WHERE id_pelanggan_src = p_id_src AND is_current = 1;
 
    IF v_exists = 0 THEN
        -- Pelanggan baru: INSERT langsung
        INSERT INTO dim_pelanggan (
            id_pelanggan_src, nama_lengkap, kota, kabupaten_kota,
            provinsi, pulau, wilayah, segmen_pelanggan,
            tgl_daftar, tahun_daftar, berlaku_dari, berlaku_sampai, is_current
        ) VALUES (
            p_id_src, p_nama, p_kota, p_kabkota, p_provinsi,
            p_pulau, p_wilayah, p_segmen, p_tgl_efektif,
            YEAR(p_tgl_efektif), p_tgl_efektif, '9999-12-31', 1
        );
    ELSE
        -- Cek apakah ada atribut yang berubah
        SELECT COUNT(*) INTO v_changed
        FROM dim_pelanggan
        WHERE id_pelanggan_src = p_id_src
          AND is_current = 1
          AND (kota             != p_kota    OR
               segmen_pelanggan != p_segmen  OR
               provinsi         != p_provinsi);
 
        IF v_changed > 0 THEN
            -- Ada perubahan: tutup record lama, buka record baru
            UPDATE dim_pelanggan
            SET berlaku_sampai = DATE_SUB(p_tgl_efektif, INTERVAL 1 DAY),
                is_current     = 0
            WHERE id_pelanggan_src = p_id_src AND is_current = 1;
 
            INSERT INTO dim_pelanggan (
                id_pelanggan_src, nama_lengkap, kota, kabupaten_kota,
                provinsi, pulau, wilayah, segmen_pelanggan,
                tgl_daftar, tahun_daftar, berlaku_dari, berlaku_sampai, is_current
            )
            SELECT id_pelanggan_src, p_nama, p_kota, p_kabkota,
                   p_provinsi, p_pulau, p_wilayah, p_segmen,
                   tgl_daftar, tahun_daftar, p_tgl_efektif, '9999-12-31', 1
            FROM dim_pelanggan
            WHERE id_pelanggan_src = p_id_src
              AND is_current = 0
              AND berlaku_sampai = DATE_SUB(p_tgl_efektif, INTERVAL 1 DAY)
            LIMIT 1;
        END IF;
        -- Jika tidak ada perubahan: tidak lakukan apa-apa (idempotent)
    END IF;
END //
DELIMITER ;
 
-- Contoh pemanggilan prosedur:
CALL upsert_pelanggan_scd2(501, 'Siti Rahayu', 'Jakarta', 'Kota Jakarta Pusat',
                            'DKI Jakarta', 'Jawa', 'Jabodetabek', 'Gold', '2024-01-02');

C.7.4 Query Historis dengan SCD Type 2

-- ============================================================
-- QUERY PATTERNS β€” Memanfaatkan SCD Type 2 untuk Analitik
-- ============================================================
 
-- Query 1: Dapatkan profil TERKINI semua pelanggan aktif
SELECT kunci_pelanggan, nama_lengkap, kota, segmen_pelanggan
FROM dim_pelanggan
WHERE is_current = 1
ORDER BY nama_lengkap;
 
-- Query 2: Dapatkan profil pelanggan PADA TANGGAL TERTENTU
-- "Seperti apa data pelanggan pada 1 Juli 2023?"
SELECT kunci_pelanggan, nama_lengkap, kota, segmen_pelanggan
FROM dim_pelanggan
WHERE id_pelanggan_src = 501
  AND '2023-07-01' BETWEEN berlaku_dari AND berlaku_sampai;
-- β†’ Mengembalikan baris dengan kota = 'Semarang' (sebelum pindah 2024)
 
-- Query 3: Lihat seluruh riwayat perubahan satu pelanggan
SELECT
    kunci_pelanggan,
    nama_lengkap,
    kota,
    segmen_pelanggan,
    berlaku_dari,
    berlaku_sampai,
    is_current,
    DATEDIFF(
        IF(is_current = 1, CURDATE(), berlaku_sampai),
        berlaku_dari
    ) AS lama_berlaku_hari
FROM dim_pelanggan
WHERE id_pelanggan_src = 501
ORDER BY berlaku_dari;
 
-- Query 4: Analisis historis akurat β€” Revenue per kota per tahun
-- (setiap transaksi dikaitkan dengan kota pelanggan PADA SAAT transaksi)
SELECT
    pel.kota,
    w.tahun,
    COUNT(DISTINCT f.id_pesanan)  AS jumlah_pesanan,
    SUM(f.revenue_bersih)         AS total_revenue
FROM fakta_penjualan f
JOIN dim_pelanggan pel ON f.kunci_pelanggan = pel.kunci_pelanggan
JOIN dim_waktu     w   ON f.kunci_waktu     = w.kunci_waktu
WHERE w.tahun IN (2022, 2023, 2024)
GROUP BY pel.kota, w.tahun
ORDER BY w.tahun, total_revenue DESC;
-- β†’ Akurat! Siti di 2022 masuk sebagai Semarang (FK β†’ kunci 1001)
--            Siti di 2024 masuk sebagai Jakarta (FK β†’ kunci 2847)
 
-- Query 5: Berapa pelanggan yang pindah kota dalam 2 tahun terakhir?
SELECT COUNT(DISTINCT id_pelanggan_src) AS pelanggan_pindah_kota
FROM dim_pelanggan
WHERE is_current = 0                                    -- sudah punya versi baru
  AND berlaku_sampai >= DATE_SUB(CURDATE(), INTERVAL 2 YEAR);
 
-- Query 6: Analisis migrasi β€” dari kota mana ke mana pelanggan berpindah?
SELECT
    lama.kota      AS kota_asal,
    baru.kota      AS kota_tujuan,
    COUNT(*)       AS jumlah_pelanggan
FROM dim_pelanggan lama
JOIN dim_pelanggan baru
    ON lama.id_pelanggan_src = baru.id_pelanggan_src
   AND baru.berlaku_dari = DATE_ADD(lama.berlaku_sampai, INTERVAL 1 DAY)
WHERE lama.kota != baru.kota                            -- pastikan kota berubah
GROUP BY lama.kota, baru.kota
ORDER BY jumlah_pelanggan DESC;

C.8 Materi 6: SCD Type 3 β€” Sejarah Terbatas

C.8.1 Mekanisme SCD Type 3

SCD TYPE 3 β€” ADD NEW COLUMN (Tambah Kolom Baru)
  Menyimpan nilai sebelumnya (HANYA SATU TINGKAT SEBELUMNYA)
  dalam kolom baru yang ditambahkan ke tabel dimensi.

  Tidak ada baris baru β€” yang ada adalah kolom baru!
  Surrogate key TIDAK berubah.

KAPAN DIGUNAKAN:
  βœ“ Hanya butuh melacak "nilai sebelumnya" (bukan semua riwayat)
  βœ“ Dimensi punya perubahan besar tapi terprediksi (mis: restrukturisasi
    organisasi, perubahan segmentasi pelanggan nasional)
  βœ“ Bisnis butuh bisa laporan dengan "skema baru" DAN
    "skema lama" secara bersamaan untuk periode transisi
  βœ— TIDAK COCOK jika perubahan bisa terjadi lebih dari 1 kali
    (kolom "sebelumnya" hanya bisa menyimpan 1 versi lama)

CONTOH β€” Restrukturisasi segmentasi pelanggan (hanya 1 kali besar):
  Perusahaan mengubah skema segmentasi:
  LAMA: 'Bronze', 'Silver', 'Gold', 'Platinum'
  BARU: 'Reguler', 'Setia', 'VIP', 'Super VIP'

  Dengan SCD Type 3, tambahkan kolom baru:
  ALTER TABLE dim_pelanggan
  ADD COLUMN segmen_lama    VARCHAR(30) NULL AFTER segmen_pelanggan,
  ADD COLUMN tgl_ubah_segmen DATE       NULL AFTER segmen_lama;

  SEBELUM perubahan:
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ kunci_pelβ”‚ nama            β”‚ segmen       β”‚ segmen_lama        β”‚
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚ 1001     β”‚ Siti Rahayu     β”‚ Gold         β”‚ NULL               β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

  SESUDAH perubahan (migrasi segmentasi):
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ kunci_pelβ”‚ nama            β”‚ segmen       β”‚ segmen_lama        β”‚
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚ 1001     β”‚ Siti Rahayu     β”‚ VIP          β”‚ Gold               β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  β†’ Surrogate key SAMA β†’ tidak ada baris baru
  β†’ Laporan bisa menggunakan segmen untuk "skema baru"
    DAN segmen_lama untuk "skema lama" dalam periode transisi

C.8.2 Implementasi SQL β€” SCD Type 3

-- ============================================================
-- SCD TYPE 3 β€” Implementasi
-- ============================================================
 
-- Tambah kolom baru ke dimensi (dilakukan SEKALI saat kebijakan berubah)
ALTER TABLE dim_pelanggan
    ADD COLUMN segmen_sebelumnya  VARCHAR(30) NULL
        COMMENT 'Segmen pelanggan sebelum restrukturisasi Januari 2024'
        AFTER segmen_pelanggan,
    ADD COLUMN tgl_ubah_segmen    DATE        NULL
        COMMENT 'Tanggal perubahan segmentasi mulai berlaku'
        AFTER segmen_sebelumnya;
 
-- Update: simpan nilai lama ke kolom baru, isi kolom utama dengan nilai baru
UPDATE dim_pelanggan
SET segmen_sebelumnya = segmen_pelanggan,   -- simpan nilai lama
    segmen_pelanggan  = CASE               -- ganti dengan nilai baru
        WHEN segmen_pelanggan = 'Bronze'   THEN 'Reguler'
        WHEN segmen_pelanggan = 'Silver'   THEN 'Setia'
        WHEN segmen_pelanggan = 'Gold'     THEN 'VIP'
        WHEN segmen_pelanggan = 'Platinum' THEN 'Super VIP'
        ELSE segmen_pelanggan
    END,
    tgl_ubah_segmen = '2024-01-01'
WHERE is_current = 1;
 
-- Query dengan skema BARU:
SELECT segmen_pelanggan AS segmen_2024, COUNT(*) AS jumlah
FROM dim_pelanggan WHERE is_current = 1 GROUP BY segmen_pelanggan;
 
-- Query dengan skema LAMA (untuk perbandingan historis):
SELECT segmen_sebelumnya AS segmen_2023, COUNT(*) AS jumlah
FROM dim_pelanggan WHERE is_current = 1 GROUP BY segmen_sebelumnya;
 
-- Query perbandingan transisi:
SELECT segmen_sebelumnya AS segmen_lama,
       segmen_pelanggan  AS segmen_baru,
       COUNT(*)           AS jumlah_pelanggan
FROM dim_pelanggan
WHERE is_current = 1 AND segmen_sebelumnya IS NOT NULL
GROUP BY segmen_sebelumnya, segmen_pelanggan
ORDER BY jumlah_pelanggan DESC;

C.9 Materi 7: SCD Type 4 & Type 6 β€” Variasi Lanjutan

C.9.1 SCD Type 4 β€” Tabel Historis Terpisah

SCD TYPE 4 β€” HISTORY TABLE (Tabel Historis Terpisah)
  Pisahkan tabel aktif (current) dan tabel historis ke dua tabel berbeda.
  Tabel utama hanya berisi versi terkini, tabel historis menyimpan semua versi lama.

KAPAN DIGUNAKAN:
  βœ“ Ketika dimensi berubah sangat sering (semi-volatile) β€” Type 2 membuat
    tabel jadi terlalu besar dan lambat
  βœ“ Ketika mayoritas query hanya butuh data terkini (query ke tabel utama
    selalu cepat karena tidak ada baris historis)

STRUKTUR:
  dim_pelanggan_current    ← hanya nilai TERKINI, 1 baris per pelanggan
  dim_pelanggan_history    ← semua versi lama, bisa banyak baris per pelanggan

  Tabel current di-JOIN ke fakta untuk analisis umum (cepat).
  Tabel history di-JOIN hanya saat butuh analisis historis point-in-time.

C.9.2 SCD Type 6 β€” Hybrid (Kombinasi Type 1 + 2 + 3)

SCD TYPE 6 β€” HYBRID (juga dikenal sebagai "Type 1+2+3" atau "Type 6")
  Menggabungkan tiga pendekatan sekaligus untuk mendapatkan fleksibilitas maksimum:
  
  β€’ Type 2: Baris baru saat ada perubahan (riwayat penuh tersimpan)
  β€’ Type 1: Semua versi diperbarui dengan nilai terkini di satu kolom khusus
  β€’ Type 3: Kolom untuk nilai sebelumnya

STRUKTUR TABEL:
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚kunci_pel β”‚ nama       β”‚ kota     β”‚ kota_terkiniβ”‚ kota_sebelum β”‚ berlaku_   β”‚ is_curr  β”‚
  β”‚          β”‚            β”‚ (historisβ”‚ (Type 1 β€”   β”‚ (Type 3)     β”‚ dari/sampaiβ”‚          β”‚
  β”‚          β”‚            β”‚ saat ini)β”‚ selalu baru)β”‚              β”‚            β”‚          β”‚
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚ 1001     β”‚ Siti       β”‚ Semarang β”‚ Jakarta     β”‚ Semarang     β”‚ 2022-01-15 β”‚ 0        β”‚ ← versi lama
  β”‚ 2847     β”‚ Siti       β”‚ Jakarta  β”‚ Jakarta     β”‚ Semarang     β”‚ 2024-01-02 β”‚ 1        β”‚ ← versi baru
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

  Manfaat:
  β†’ kota: "di mana pelanggan SAAT transaksi terjadi" (historis akurat)
  β†’ kota_terkini: "di mana pelanggan SEKARANG" (bisa dari semua versi lama)
  β†’ kota_sebelumnya: transisi perubahan terakhir

  Kelemahan: Kompleks, tabel lebih lebar, ETL lebih rumit.
  Direkomendasikan hanya jika benar-benar diperlukan.

C.10 Materi 8: Decision Matrix SCD & Best Practices Dimensional Modelling

C.10.1 Decision Matrix β€” Pilih SCD Type untuk Setiap Atribut

PANDUAN MEMILIH SCD TYPE PER ATRIBUT:

Untuk setiap atribut yang bisa berubah, jawab 3 pertanyaan:

Q1: Apakah perubahan ini perlu dilacak historisnya untuk analitik?
  β†’ TIDAK (mis: typo, data koreksi, info tidak relevan)
    β†’ SCD TYPE 1 (timpa saja)

Q2: Apakah kamu butuh menjawab "bagaimana kondisi X saat transaksi Y terjadi?"
  β†’ YA (mis: kota, segmen, jabatan, kategori produk)
    β†’ SCD TYPE 2 (baris baru)

Q3: Apakah perubahan hanya terjadi 1 kali besar dan kamu butuh
    laporan versi lama DAN baru secara bersamaan?
  β†’ YA (mis: restrukturisasi segmentasi, rebranding)
    β†’ SCD TYPE 3 (tambah kolom)
  β†’ TIDAK β†’ kembali ke Type 2

TABEL KEPUTUSAN PER ATRIBUT DIMENSI β€” dim_pelanggan:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Atribut                 β”‚ SCD Type β”‚ Alasan                                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ nama_lengkap            β”‚ Type 1   β”‚ Perubahan karena typo atau nama resmi (misal  β”‚
β”‚                         β”‚          β”‚ setelah menikah) β€” tidak perlu historis        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ jenis_kelamin           β”‚ Type 1   β”‚ Hampir tidak berubah; jika ada: koreksi data   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ no_telepon              β”‚ Type 1   β”‚ Tidak ada nilai analitik dari nomor HP lama    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ email                   β”‚ Type 1   β”‚ Sama seperti no_telepon                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ kota                    β”‚ Type 2   β”‚ Kunci analisis geografis historis β€” "revenue   β”‚
β”‚                         β”‚          β”‚ dari kota X di periode Y" harus akurat         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ provinsi                β”‚ Type 2   β”‚ Sama dengan kota (hierarki lokasi)             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ segmen_pelanggan        β”‚ Type 2   β”‚ Analisis cohort segmen: "pelanggan yang naik   β”‚
β”‚                         β”‚          β”‚ ke Gold β€” berapa lama sampai churn?"           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ kelompok_usia           β”‚ Type 2   β”‚ Bisa berubah seiring usia β€” relevan untuk      β”‚
β”‚                         β”‚          β”‚ analisis lifecycle pelanggan                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ tgl_daftar              β”‚ Type 1   β”‚ Tidak berubah; jika ada: koreksi data saja     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

TABEL KEPUTUSAN β€” dim_produk:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Atribut                 β”‚ SCD Type β”‚ Alasan                                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ nama_produk             β”‚ Type 1   β”‚ Perubahan nama biasanya koreksi; jika         β”‚
β”‚                         β”‚          β”‚ rebranding besar β†’ pertimbangkan Type 2        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ kategori                β”‚ Type 2   β”‚ Perpindahan kategori mempengaruhi analisis     β”‚
β”‚                         β”‚          β”‚ per kategori historis β€” harus akurat           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ harga_jual              β”‚ Type 2   β”‚ "Berapa revenue dengan harga lama vs baru?"   β”‚
β”‚                         β”‚          β”‚ β€” pertanyaan valid yang butuh historis         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ rentang_harga           β”‚ Type 2   β”‚ Derived dari harga β€” ikut Type 2              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ nama_supplier           β”‚ Type 1   β”‚ Perubahan nama supplier biasanya rebrand;     β”‚
β”‚                         β”‚          β”‚ analitis lebih umum per kode/id supplier       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ teknik_pembuatan        β”‚ Type 1   β”‚ Jarang berubah; jika berubah: koreksi data    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ is_aktif                β”‚ Type 1   β”‚ Status saat ini (aktif/tidak) β€” not historical β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

C.10.2 Best Practices Dimensional Modelling β€” Ringkasan Komprehensif

Ini adalah panduan menyeluruh yang merangkum semua best practice dari P11–P13.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
BEST PRACTICES DESAIN FAKTA
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

BP-F1: Pilih grain yang paling atomik yang masuk akal secara bisnis
  β†’ Grain aggregate = kehilangan kemampuan drill-down permanen
  β†’ Jika ragu, pilih grain lebih rendah β€” bisa agregasi, tapi tidak bisa
    mengembalikan detail yang sudah hilang

BP-F2: Semua measures harus pada grain yang sama
  β†’ Jangan campurkan "total per pesanan" dan "total per item" dalam satu baris

BP-F3: Prioritaskan additive measures
  β†’ Simpan komponen aditif (qty, revenue) bukan rasio atau persentase
  β†’ Persentase bisa dihitung dari komponen: margin% = laba/revenue

BP-F4: Sertakan degenerate dimensions untuk identitas transaksi
  β†’ id_pesanan, nomor_faktur dll. perlu ada untuk drill-through ke OLTP

BP-F5: Partisi tabel fakta berdasarkan waktu
  β†’ Untuk tabel dengan ratusan juta baris, PARTITION BY RANGE (kunci_waktu)
    meningkatkan performa query drastis (pruning partisi)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
BEST PRACTICES DESAIN DIMENSI
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

BP-D1: Selalu gunakan surrogate key sebagai PK dimensi
  β†’ Integer auto-increment β€” tidak punya makna bisnis
  β†’ Natural key tetap disimpan sebagai kolom terpisah

BP-D2: Denormalize dimensi β€” flatten semua hierarki
  β†’ Pilih STAR sebagai default, bukan snowflake
  β†’ Redundansi yang disengaja = investasi untuk performa query

BP-D3: Buat dimensi selebar mungkin
  β†’ Tambahkan atribut derivatif: kelompok_usia, rentang_harga, nama_hari_id
  β†’ Setiap kolom dimensi = satu kemungkinan filter/grouping analitik baru

BP-D4: dim_waktu selalu wajib ada dan pre-populated
  β†’ Jangan simpan tanggal tanpa dim_waktu
  β†’ Populate untuk rentang 5–10 tahun ke depan sekaligus

BP-D5: Tentukan strategi SCD per atribut sebelum implementasi
  β†’ Atribut koreksi: Type 1
  β†’ Atribut yang mempengaruhi analisis historis: Type 2
  β†’ Restrukturisasi sekali besar dengan kebutuhan laporan transisi: Type 3

BP-D6: Simpan "row description" di setiap dimensi
  β†’ Kolom teks tunggal yang menjelaskan baris: "Budi Santoso - Semarang - Gold"
  β†’ Berguna untuk BI tools, debugging, dan laporan drill-through

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
BEST PRACTICES SKEMA DAN NAMING CONVENTION
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

BP-N1: Naming convention konsisten di seluruh warehouse
  β†’ Tabel fakta: fakta_[proses_bisnis] (contoh: fakta_penjualan)
  β†’ Tabel dimensi: dim_[entitas] (contoh: dim_pelanggan)
  β†’ Surrogate key: kunci_[entitas] (contoh: kunci_pelanggan)
  β†’ Natural key: id_[entitas]_src (contoh: id_pelanggan_src)
  β†’ Tanggal SCD: berlaku_dari, berlaku_sampai, is_current

BP-N2: Beri komentar SQL yang informatif
  β†’ Komentar tabel: apa grain-nya, apa tujuan tabel ini
  β†’ Komentar kolom: apa maknanya, apakah ada logika derivasi khusus

BP-N3: Gunakan conformed dimensions lintas proses bisnis
  β†’ Satu dim_waktu, satu dim_pelanggan β€” dipakai oleh semua tabel fakta
  β†’ Jangan buat dim_waktu2 yang sedikit berbeda!

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
BEST PRACTICES ETL DAN PEMELIHARAAN
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

BP-E1: Load dimensi SEBELUM fakta β€” selalu
  β†’ FK constraint tidak bisa dipenuhi jika dimensi belum ada

BP-E2: Buat ETL bersifat idempotent
  β†’ Menjalankan ETL dua kali dengan data yang sama tidak menghasilkan
    duplikasi atau perubahan yang tidak diinginkan

BP-E3: Audit trail di ETL
  β†’ Catat: kapan baris pertama kali dimasukkan (etl_load_timestamp)
  β†’ Ini berbeda dari berlaku_dari β€” berlaku_dari adalah tanggal bisnis,
    etl_load_timestamp adalah tanggal teknis ETL dijalankan

BP-E4: Jangan DELETE dari warehouse β€” gunakan soft delete
  β†’ Jika data sumber dihapus di OLTP, tandai di warehouse dengan
    is_aktif = 0 atau is_deleted = 1, jangan DELETE dari fakta/dimensi
  β†’ Ini melindungi integritas historis

BP-E5: Monitoring dan alerting pada proses ETL
  β†’ Alert jika ETL gagal atau terlambat dari jadwal
  β†’ Dashboard kualitas data: berapa baris berhasil di-load vs ditolak

D. LATIHAN DAN DISKUSI

D.1 Latihan Individual: Tentukan Strategi SCD (10 menit)

Instruksi: Diberikan dimensi dim_dokter dari sistem data warehouse rumah sakit, tentukan SCD Type yang tepat untuk setiap atribut. Berikan alasan singkat.

Tabel dim_dokter (atribut-atributnya):

NoAtributKemungkinan PerubahanSCD Type yang TepatAlasan
1nama_dokterPergantian nama setelah pernikahan atau gelar bertambah??
2spesialisasiDokter umum menyelesaikan spesialisasi β†’ jadi dokter spesialis??
3sub_spesialisasiBisa bertambah setelah fellowship/pelatihan lanjutan??
4no_strSurat Tanda Registrasi bisa diperbarui periodik??
5status_kepegawaian'Tetap' / 'Kontrak' / 'Paruh Waktu' β€” bisa berubah??
6departemenBisa pindah departemen/poli??
7no_teleponBisa ganti nomor??
8tarif_konsultasiBisa naik setiap tahun atau setelah promosi jabatan??
9adalah_aktifDokter bisa resign, cuti panjang, atau pensiun??
10email_rumah_sakitEmail kantor bisa berubah jika ganti divisi??

D.2 Praktikum Kelompok: Update Star Schema Proyek dengan Strategi SCD (15 menit)

Instruksi: Setiap kelompok membuka dokumen star schema yang telah dikumpulkan untuk tugas P12. Diskusikan dan lengkapi strategi SCD untuk setiap atribut di setiap dimensi.

Format Output (tambahkan ke dokumen proyek):

Untuk setiap dimensi, buat tabel keputusan SCD:

DIMENSI: dim_[nama_entitas]

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Atribut               β”‚ SCD Type β”‚ Justifikasi                                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ [nama_atribut_1]      β”‚ Type [?] β”‚ [Alasan bisnis mengapa type ini dipilih]       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ [nama_atribut_2]      β”‚ Type [?] β”‚ ...                                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

ATRIBUT YANG MEMERLUKAN SCD TYPE 2:
  Kolom berlaku_dari, berlaku_sampai, is_current sudah ada di DDL P12.
  Verifikasi bahwa kolom-kolom ini ada dan tipe datanya benar!

PERTANYAAN ANALITIK HISTORIS yang kini bisa dijawab (berkat SCD Type 2):
  1. "_____________________________________ di periode ______?"
  2. "_____________________________________ sebelum vs sesudah _____?"

Diskusi kelas (5 menit): 2–3 kelompok presentasikan keputusan SCD paling menarik atau paling debatable dari domain masing-masing.


D.3 Diskusi: Star vs Snowflake β€” Kasus Keputusan Nyata (5 menit)

Dosen memimpin diskusi singkat dengan dua pertanyaan pemancing:

  1. "Ada yang punya dimensi dengan hierarki sangat dalam di proyek kalian? Kira-kira 4+ level? Apakah kalian mempertimbangkan snowflake untuk bagian itu?"

  2. "Dalam proyek data warehouse nyata, apakah menurutmu developer lebih sering menyesal karena 'terlalu banyak normalisasi' (snowflake) atau 'kurang normalisasi' (star)? Mengapa?"


E. EVALUASI DAN PENILAIAN

E.1 Kuis Penutup (10 menit, bobot partisipasi)

  1. Sebutkan 3 keunggulan star schema dibanding snowflake schema dan 2 keunggulan snowflake dibanding star. Berdasarkan trade-off itu, dalam kondisi apa kamu akan memilih snowflake?

  2. Jelaskan dengan ilustrasi angka/tabel konkret: apa yang terjadi terhadap laporan "Revenue per kota tahun 2022" jika kita menggunakan SCD Type 1 ketika pelanggan pindah kota di 2024? Mengapa ini menjadi masalah?

  3. Diberikan situasi: "Sistem perpustakaan kampus mengubah skema klasifikasi koleksi dari DDC (Dewey Decimal) ke sistem lokal pada Januari 2024. Ratusan buku berpindah kelas sekaligus." SCD Type berapa yang paling tepat untuk atribut kelas_koleksi di dim_buku? Jelaskan alasannya!

  4. Tulis pseudocode atau SQL singkat (5–8 baris) untuk proses SCD Type 2 saat seorang karyawan pindah divisi.

  5. Dari daftar best practices dimensional modelling, pilih 2 yang menurutmu paling sering dilanggar oleh pemula dan jelaskan mengapa melanggarnya berbahaya!

E.2 Tugas Penyempurnaan: Integrasi SCD ke Star Schema Proyek

Judul: Penyempurnaan Star Schema Proyek dengan Strategi SCD

Deskripsi: Ini adalah penyempurnaan dari Tugas P12. Mahasiswa memperbarui dokumen dan kode SQL proyek dengan strategi SCD yang eksplisit.

Deliverables Tambahan (melengkapi tugas P12):

Bagian Baru 1 β€” Dokumen Keputusan SCD (1 halaman)

  • Untuk setiap dimensi di proyek: tabel keputusan SCD per atribut (seperti format D.2)
  • Kolom berlaku_dari, berlaku_sampai, is_current diverifikasi sudah ada di DDL
  • Justifikasi bisnis untuk setiap keputusan SCD

Bagian Baru 2 β€” Implementasi SQL SCD Type 2 (file .sql)

  • Pilih 1 dimensi dari proyek yang memiliki atribut SCD Type 2
  • Tulis SQL lengkap: INSERT awal, UPDATE saat perubahan (SCD Type 2), dan minimal 2 query historis yang memanfaatkan mekanisme SCD

Bagian Baru 3 β€” Refleksi Desain (0.5 halaman)

  • Apakah ada keputusan desain di P12 yang perlu diubah setelah memahami SCD?
  • Apakah ada atribut yang seharusnya di-denormalize atau di-normalize lebih lanjut?
  • Jika domain proyek ini menggunakan snowflake schema untuk salah satu dimensi, dimensi mana yang paling masuk akal dan mengapa?

Format: Tambahan ke dokumen PDF P12 (update versi) + update file SQL P12 Deadline: H-1 sebelum Pertemuan 14 (dikumpulkan via Ngaji UIN Gusdur, menggantikan versi lama) Nama file: StarSchema_SCD_[KelompokX]_[Domain].pdf dan StarSchema_SCD_[KelompokX]_[Domain].sql


F. PERSIAPAN PERTEMUAN 14

F.1 Topik Pertemuan 14

Integrasi Model Data dalam Proyek Sains Data β€” pertemuan ini adalah jembatan penutup yang menghubungkan seluruh semester: bagaimana model data (dari ERD hingga dimensional model) menjadi fondasi untuk pipeline analitik dan machine learning.

Topik spesifik:

  • Bagaimana data di warehouse (dimensional model) menjadi bahan baku feature engineering untuk ML
  • Konsep feature store sebagai jembatan antara data warehouse dan model ML
  • Pipeline data end-to-end: OLTP β†’ ETL β†’ Warehouse β†’ Feature Engineering β†’ ML Model
  • Review dan feedback proyek kelompok (setiap kelompok mendapat waktu singkat untuk presentasi progress)
  • Persiapan menuju presentasi akhir (P15)

F.2 Pertanyaan Pemantik untuk Pertemuan 14

Dari dimensional model proyek kelompok yang sudah kalian rancang dan sempurnakan:

  1. Kolom-kolom apa di dimensi pelanggan/pengguna kalian yang paling berguna sebagai fitur klasifikasi untuk model prediksi (misalnya prediksi churn, prediksi pembelian berikutnya)?

  2. Measures di tabel fakta kalian β€” mana yang bisa langsung digunakan sebagai fitur? Mana yang perlu diagregasi dulu (misalnya: bukan per transaksi, tapi total 3 bulan terakhir per pelanggan)?

  3. Jika kamu harus membangun model prediksi sederhana dari data warehouse proyekmu, pertanyaan bisnis apa yang paling berguna untuk dijawab? Dan label target (y) apa yang akan kamu gunakan?

F.3 Yang Harus Dipersiapkan Sebelum P14

  1. Review kembali star schema proyek yang sudah diperbarui dengan SCD β€” pastikan sudah dikumpulkan ke Ngaji UIN Gusdur
  2. Pikirkan minimal 5 fitur yang bisa diekstrak dari warehouse untuk model prediksi
  3. Siapkan deskripsi singkat progress proyek (2–3 menit untuk presentasi kilat di P14)
  4. Baca (opsional): Zheng & Casari, "Feature Engineering for Machine Learning" β€” Chapter 1–2 (tersedia di Google Scholar)

G. REFERENSI

G.1 Referensi Utama

  1. Kimball, R. & Ross, M. (2013). The Data Warehouse Toolkit: The Definitive Guide to Dimensional Modeling (3rd Edition). Wiley.

    • Chapter 5: Procurement (contoh SCD Type 2 dalam konteks nyata β€” sangat direkomendasikan)
    • Chapter 6: Order Management (kompleksitas penanganan perubahan dimensi)
    • Chapter 7: Accounting (contoh semi-additive measures dan snapshot facts)
  2. Kimball, R. & Ross, M. (2013). Bab yang sama, khusus untuk Snowflake:

    • Chapter 9: Human Resources Management (contoh dimensi yang berubah sering)
    • Appendix A: "The Kimball Dimensional Modeling Techniques" (ringkasan semua teknik, termasuk SCD)
  3. Elmasri, R. & Navathe, S. B. (2015). Fundamentals of Database Systems (7th Edition). Pearson.

    • Chapter 29: Data Warehousing β€” bagian SCD dan skema variasi

G.2 Referensi Online

  1. Kimball Group. "Slowly Changing Dimensions" (Design Tips #1, salah satu artikel paling populer):

  2. Kimball Group. "The 10 Essential Rules of Dimensional Modeling":

  3. dbt Labs. "The Guide to Slowly Changing Dimensions":

  4. AWS Big Data Blog. "Implement Slowly Changing Dimensions in a Data Lake":

G.3 Video Resources

  1. Kahan Data Solutions β€” "Slowly Changing Dimensions Type 1, 2, 3 Explained" (YouTube β€” visual dan jelas)
  2. Data with Baraa β€” "Star Schema vs Snowflake Schema β€” Full Comparison" (YouTube)
  3. Alex The Analyst β€” "SCD Type 2 Implementation in SQL" (YouTube β€” praktis, dengan contoh kode)
  4. Kimball Group β€” "Type 2 Slowly Changing Dimensions" (YouTube β€” dari sumber aslinya)

G.4 Tools untuk Eksplorasi SCD

  1. dbt (data build tool) β€” https://www.getdbt.com (opens in a new tab): framework modern untuk ETL dan transformasi yang memiliki built-in snapshot untuk SCD Type 2
  2. Apache Hive β€” mendukung ACID transactions untuk update/upsert di data warehouse on-premise
  3. Delta Lake β€” https://delta.lakehouse.io (opens in a new tab): format storage yang mendukung ACID dan SCD natively

H. LAMPIRAN

Lampiran A: Perbandingan Visual Semua Tipe SCD

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚             β”‚                                                                             β”‚
β”‚  SCD TYPE 1 β”‚ SEBELUM:  kunci=1001 | nama=Siti | kota=Semarang | segmen=Gold             β”‚
β”‚  OVERWRITE  β”‚                                                                             β”‚
β”‚             β”‚ SESUDAH:  kunci=1001 | nama=Siti | kota=Jakarta  | segmen=Gold             β”‚
β”‚             β”‚                                                                             β”‚
β”‚             β”‚ β†’ 1 baris tetap | kunci sama | riwayat HILANG                              β”‚
β”‚             β”‚ β†’ FK di fakta tidak berubah                                                 β”‚
β”‚             β”‚ β†’ Laporan historis ikut berubah                                             β”‚
β”‚             β”‚                                                                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚             β”‚                                                                             β”‚
β”‚  SCD TYPE 2 β”‚ SEBELUM:  kunci=1001 | nama=Siti | kota=Semarang | brl_dari=2022-01-15    β”‚
β”‚  ADD ROW    β”‚           berlaku_sampai=9999-12-31 | is_current=1                         β”‚
β”‚             β”‚                                                                             β”‚
β”‚             β”‚ SESUDAH:  kunci=1001 | nama=Siti | kota=Semarang | brl_dari=2022-01-15    β”‚
β”‚             β”‚           berlaku_sampai=2024-01-01 | is_current=0   ← DITUTUP             β”‚
β”‚             β”‚                                                                             β”‚
β”‚             β”‚           kunci=2847 | nama=Siti | kota=Jakarta  | brl_dari=2024-01-02    β”‚
β”‚             β”‚           berlaku_sampai=9999-12-31 | is_current=1   ← BARU               β”‚
β”‚             β”‚                                                                             β”‚
β”‚             β”‚ β†’ 2 baris | kunci baru | riwayat TERSIMPAN PENUH                           β”‚
β”‚             β”‚ β†’ FK lama di fakta tetap ke 1001 (akurat historis)                         β”‚
β”‚             β”‚ β†’ FK baru di fakta ke 2847 (akurat untuk transaksi baru)                  β”‚
β”‚             β”‚                                                                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚             β”‚                                                                             β”‚
β”‚  SCD TYPE 3 β”‚ SEBELUM:  kunci=1001 | nama=Siti | segmen=Gold | segmen_lama=NULL         β”‚
β”‚  ADD COLUMN β”‚                                                                             β”‚
β”‚             β”‚ SESUDAH:  kunci=1001 | nama=Siti | segmen=VIP   | segmen_lama=Gold        β”‚
β”‚             β”‚                                                                             β”‚
β”‚             β”‚ β†’ 1 baris tetap | kunci sama | 1 tingkat riwayat TERSIMPAN                 β”‚
β”‚             β”‚ β†’ FK di fakta tidak berubah                                                 β”‚
β”‚             β”‚ β†’ Bisa query "skema lama" via segmen_lama, "skema baru" via segmen         β”‚
β”‚             β”‚ β†’ TIDAK BISA track lebih dari 1 perubahan!                                 β”‚
β”‚             β”‚                                                                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚             β”‚                                                                             β”‚
β”‚  KAPAN      β”‚ Type 1: Koreksi data, info tanpa nilai historis, field operasional         β”‚
β”‚  PILIH MANA β”‚ Type 2: Perubahan yang mempengaruhi analisis historis (DEFAULT untuk DW)  β”‚
β”‚             β”‚ Type 3: Restrukturisasi besar 1 kali yang butuh laporan "lama" & "baru"   β”‚
β”‚             β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Lampiran B: Checklist Snowflake vs Star β€” Pengambilan Keputusan

CHECKLIST: APAKAH SNOWFLAKE LAYAK DIPERTIMBANGKAN?

Jawab pertanyaan berikut. Tambahkan poin untuk setiap jawaban YA:

ALASAN MEMPERTIMBANGKAN SNOWFLAKE (+1 per YA):
  β–‘ Storage sangat terbatas dan biaya storage adalah concern utama?      +1
  β–‘ Dimensi memiliki hierarki 4+ level yang sangat dalam?               +1
  β–‘ Nilai di sub-dimensi berubah sangat sering (mis: harga bahan baku)? +1
  β–‘ Tim technical yang akan query sangat terampil dalam SQL kompleks?   +1

ALASAN TETAP PAKAI STAR (βˆ’1 per YA):
  β–‘ BI tool utama (Tableau, Power BI, dll.) lebih optimal di star?       βˆ’1
  β–‘ Mayoritas pengguna adalah business analyst non-teknis?               βˆ’1
  β–‘ Kecepatan query adalah prioritas utama (bukan storage)?              βˆ’1
  β–‘ Ini adalah proyek pertama / DW sederhana?                            βˆ’1

KEPUTUSAN:
  Skor ≀ 0 β†’ Pilih STAR SCHEMA
  Skor 1–2 β†’ Pertimbangkan hybrid (star dengan sebagian normalisasi)
  Skor 3+  β†’ Snowflake layak dipertimbangkan

Catatan: Industri modern dengan cloud DW (Snowflake, BigQuery, Redshift)
  hampir selalu lebih suka star karena storage sangat murah dan
  columnar storage menghilangkan kelemahan star soal redundansi.

Lampiran C: Template Tabel Keputusan SCD untuk Proyek

TABEL KEPUTUSAN SCD β€” [NAMA DIMENSI]
Domain Proyek  : _________________________________
Kelompok       : _________________________________

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Atribut               β”‚ SCD Type β”‚ Justifikasi Bisnis                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                       β”‚          β”‚                                                β”‚
β”‚                       β”‚          β”‚                                                β”‚
β”‚                       β”‚          β”‚                                                β”‚
β”‚                       β”‚          β”‚                                                β”‚
β”‚                       β”‚          β”‚                                                β”‚
β”‚                       β”‚          β”‚                                                β”‚
β”‚                       β”‚          β”‚                                                β”‚
β”‚                       β”‚          β”‚                                                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

ATRIBUT YANG MENGGUNAKAN SCD TYPE 2 (daftar):
  1. ________________  Alasan: _________________________
  2. ________________  Alasan: _________________________
  3. ________________  Alasan: _________________________

VERIFIKASI KOLOM SCD TYPE 2 DI DDL (centang jika sudah ada):
  β–‘ berlaku_dari     DATE NOT NULL
  β–‘ berlaku_sampai   DATE NOT NULL DEFAULT '9999-12-31'
  β–‘ is_current       TINYINT(1) NOT NULL DEFAULT 1

PERTANYAAN ANALITIK HISTORIS yang kini bisa dijawab:
  1. "___________________________________________________________"
     β†’ Dimensi yang digunakan: ________________________________
  2. "___________________________________________________________"
     β†’ Dimensi yang digunakan: ________________________________

Lampiran D: Perbandingan Star Schema & Snowflake β€” Diagram Side-by-Side

STAR SCHEMA (dim_produk denormalized):

     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚ fakta_penjualan                                    β”‚
     β”‚ kunci_produk FK ──────────────────────────────────►│
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                          β”‚
                                               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                               β”‚ dim_produk                           β”‚
                                               β”‚ kunci_produk      PK                 β”‚
                                               β”‚ nama_produk                          β”‚
                                               β”‚ subkategori   ← FLAT, semua dalam    β”‚
                                               β”‚ kategori      ← satu tabel           β”‚
                                               β”‚ kelompok_kat  ←                      β”‚
                                               β”‚ nama_supplier ←                      β”‚
                                               β”‚ kota_supplier ←                      β”‚
                                               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Query: 2 JOIN (fact + dim_produk)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

SNOWFLAKE SCHEMA (dim_produk dinormalisasi):

     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚ fakta_penjualan                                    β”‚
     β”‚ kunci_produk FK ──────────────────────────────────►│
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                          β”‚
                                               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                               β”‚ dim_produk           β”‚
                                               β”‚ kunci_produk    PK   β”‚
                                               β”‚ nama_produk          β”‚
                                               β”‚ kunci_subkat    FK β”€β”€β–Ίβ”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                               β”‚ kunci_supplier  FK ──►│ dim_subkat   β”‚
                                               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚ kunci_subkat β”‚
                                                                       β”‚ nama_subkat  β”‚
                                               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ kunci_kat FK β”œβ”€β”€β–Ίβ”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                               β”‚ dim_supplier          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚ dim_kategori β”‚
                                               β”‚ kunci_supplier  PK                       β”‚ kunci_kat  PKβ”‚
                                               β”‚ nama_supplier                            β”‚ nama_kat     β”‚
                                               β”‚ kota_supplier                            β”‚ kunci_kel FKβ”€β–Ίβ”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚dim_kelom β”‚
Query: 4–5 JOIN (fact + produk + subkat + kat + kelompok + supplier)                                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Lampiran E: Lembar Kerja Praktikum D.2 β€” Keputusan SCD Proyek

LEMBAR KERJA SCD β€” PROYEK KELOMPOK
Kelompok : _____ | Domain : ___________________ | Tanggal: _________

DIMENSI 1: dim_____________

  Proses bisnis utama : ________________________________
  Atribut yang dievaluasi:

  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ Atribut           β”‚ SCD Type β”‚ Alasan Bisnis                           β”‚
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚                   β”‚ Type     β”‚                                        β”‚
  β”‚                   β”‚ Type     β”‚                                        β”‚
  β”‚                   β”‚ Type     β”‚                                        β”‚
  β”‚                   β”‚ Type     β”‚                                        β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

DIMENSI 2: dim_____________

  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ Atribut           β”‚ SCD Type β”‚ Alasan Bisnis                           β”‚
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚                   β”‚ Type     β”‚                                        β”‚
  β”‚                   β”‚ Type     β”‚                                        β”‚
  β”‚                   β”‚ Type     β”‚                                        β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

PILIH 1 ATRIBUT UNTUK IMPLEMENTASI SCD TYPE 2:
  Dimensi        : dim___________
  Atribut        : _______________
  Alasan dipilih : _________________________________________

  Tulis PSEUDOCODE proses SCD Type 2 untuk atribut ini:
  
  SAAT NILAI BERUBAH:
  Step 1: UPDATE _______ SET berlaku_sampai = [kemarin], is_current = 0
          WHERE id_src = [id] AND is_current = 1
  
  Step 2: INSERT INTO _______ VALUES (
              id_src = [sama],
              [atribut_berubah] = [nilai baru],
              [atribut_lain] = [sama dengan sebelumnya],
              berlaku_dari = [hari ini],
              berlaku_sampai = '9999-12-31',
              is_current = 1
          )

  QUERY HISTORIS yang kini bisa dijawab:
  "[__________________________________________________ pada periode ______?]"
  SQL: SELECT _____ FROM _____ WHERE _____ BETWEEN _____ AND _____;

Lampiran F: SCD Quick Reference β€” Decision Matrix Permanen

Gunakan tabel ini sebagai referensi cepat permanen saat menentukan strategi SCD untuk setiap atribut dimensi.

Ringkasan 5 Tipe SCD

TipeNamaStrategiHistoris?KompleksitasKasus Penggunaan Utama
Type 0FixedTidak pernah diupdateTidak adaSangat rendahTanggal lahir, nomor kontrak awal
Type 1OverwriteTimpa nilai lamaTidak adaRendahKoreksi typo, data tidak relevan historis
Type 2Add RowTambah baris baruPenuhTinggiPerubahan yang butuh point-in-time analysis
Type 3Add ColumnTambah kolom "sebelumnya"Terbatas (1 generasi)SedangRestrukturisasi besar, dua versi bersamaan
Type 6HybridType 1+2+3Penuh + current flagSangat tinggiEnterprise DW dengan kebutuhan analitik kompleks

Decision Tree Per Atribut

PertanyaanJawaban→ SCD Type
Apakah nilai atribut ini pernah berubah?Tidak pernahType 0
Apakah perubahan ini hanya koreksi data (typo, data salah)?YaType 1
Apakah query analitik perlu menjawab "kondisi X saat transaksi Y"?YaType 2
Apakah perubahan hanya terjadi sekali dan butuh laporan transisi?YaType 3
Apakah butuh historis penuh + flag current + nilai sebelumnya?YaType 6
Tidak tahu / tidak yakinDefault amanType 2

Panduan Per Jenis Atribut Dimensi

Jenis AtributContohSCD yang DisarankanAlasan
Informasi kontakemail, nomor HPType 1Tidak ada nilai analitik dari versi lama
Lokasi/geografikota, provinsiType 2Relevan untuk analisis geografis historis
Segmentasi pelangganGold/Silver/BronzeType 2Analisis cohort, churn analysis
Harga produkharga jualType 2β€œRevenue dengan harga lama vs baru?”
Kategori produksub-kategori, jenisType 2Analisis per kategori historis
Status aktifis_aktifType 1Status terkini saja yang relevan
Nama & mereknama produk, nama tokoType 1 (default) / Type 2 (rebranding besar)Tergantung apakah nama lama masih dicari
Jabatan/posisi karyawanmanager, supervisorType 2Analisis karier, perubahan tanggung jawab
Identitas tetapNIM, NIK, NPWPType 0Tidak boleh berubah

Kolom Wajib untuk SCD Type 2

-- Tambahkan 3 kolom ini ke setiap dimensi yang menggunakan Type 2:
berlaku_dari     DATE        NOT NULL,   -- tanggal mulai berlaku versi ini
berlaku_sampai   DATE        NOT NULL,   -- '9999-12-31' untuk versi current
is_current       TINYINT(1)  NOT NULL,   -- 1 = current, 0 = historis
 
-- Contoh query untuk mendapatkan versi yang berlaku pada tanggal tertentu:
SELECT * FROM dim_pelanggan
WHERE id_pelanggan_src = 1001
  AND '2024-06-15' BETWEEN berlaku_dari AND berlaku_sampai;
 
-- Contoh query untuk mendapatkan versi current:
SELECT * FROM dim_pelanggan
WHERE id_pelanggan_src = 1001
  AND is_current = 1;

Aturan praktis: Jika ragu antara Type 1 dan Type 2, pilih Type 2. Lebih mudah mengubah Type 2 menjadi Type 1 (dengan mengabaikan historis) daripada mengubah Type 1 menjadi Type 2 (historis sudah hilang dan tidak bisa dikembalikan).


PENUTUP

Pertemuan 13 melengkapi babak dimensional modelling semester ini dengan dua topik yang sangat praktis dan sangat sering dihadapi di dunia nyata.

Key Messages Pertemuan 13:

  1. Star schema adalah default β€” snowflake adalah pengecualian β€” dalam era cloud data warehouse yang murah, alasan untuk memilih snowflake semakin berkurang. Sebelum memilih snowflake, pastikan ada alasan kuat yang tidak bisa diatasi oleh star schema.

  2. Data berubah adalah kepastian, bukan pengecualian β€” data warehouse yang tidak menyiapkan strategi SCD sejak awal akan menghadapi masalah integritas historis yang serius. SCD harus direncanakan sebelum implementasi, bukan setelah.

  3. Tidak semua perubahan harus diperlakukan sama β€” dalam satu dimensi, atribut yang berbeda bisa memerlukan SCD Type yang berbeda. Kuncinya adalah pertanyaan bisnis: "Apakah riwayat perubahan atribut ini punya nilai analitik?"

  4. SCD Type 2 adalah pilihan paling aman untuk data warehouse β€” meski tabel jadi lebih besar, ia memberikan kemampuan point-in-time analysis yang tidak bisa dicapai dengan cara lain. Tiga kolom kecil (berlaku_dari, berlaku_sampai, is_current) adalah investasi kecil dengan manfaat sangat besar.

  5. Best practices bukan aturan kaku β€” setiap trade-off dalam dimensional modelling harus disesuaikan dengan kebutuhan bisnis, kemampuan tim, dan batasan teknis. Yang terpenting adalah memahami mengapa setiap keputusan dibuat.

Koneksi ke Pertemuan 14–15: Dengan selesainya P13, kelompok kini memiliki desain data yang lengkap: ERD (P2–P4), normalisasi dan logical model (P5–P7), physical model (P8–P9), data quality (P10), dan dimensional model dengan SCD (P11–P13). Pertemuan 14 akan menunjukkan bagaimana semua ini menjadi fondasi untuk sains data dan machine learning. Pertemuan 15 adalah panggung presentasi proyek akhir.


Disusun oleh: Mohammad Reza Maulana, M.Kom Program Studi Sains Data Fakultas Ekonomi dan Bisnis Islam UIN K.H. Abdurrahman Wahid Pekalongan

Revisi: Februari 2026