SELECT INTO dan Tabel Staging untuk Alur Laporan Bulanan
Blog/Tutorial SQL/SELECT INTO dan Tabel Staging untuk Alur Laporan Bulanan

SELECT INTO dan Tabel Staging untuk Alur Laporan Bulanan

BimaBima
·29 Agustus 2025·12 menit baca

Penulis

Bima

Bima

Founder & Data Professional

Bagikan

TL;DR

SELECT INTO bikin tabel baru dari hasil sebuah query, dan strukturnya ngikutin kolom yang kamu pilih. Di SQL Server sintaksnya SELECT kolom INTO tabel_baru FROM sumber, sedangkan di PostgreSQL, MySQL, dan SQLite yang dipakai CREATE TABLE AS SELECT. Perintah ini cocok buat bikin tabel staging, yaitu tabel antara yang nampung hasil olahan supaya query laporan berikutnya nggak ngulang kerjaan berat yang sama.

SELECT INTO bikin tabel baru dari hasil sebuah query. Kolom dan tipe datanya ngikutin apa yang kamu SELECT, jadi kamu nggak perlu nulis CREATE TABLE duluan.

Perintah ini paling sering kepakai buat satu hal: bikin tabel staging, yaitu tabel antara yang nampung hasil olahan biar query berikutnya nggak ngulang kerjaan berat yang sama.

Di bawah ini ada sintaksnya per database, alur staging tiga lapis buat laporan bulanan, pola biar query-nya aman dijalanin ulang, plus jebakan yang sering bikin data laporan salah.

Apa itu SELECT INTO dan kapan dipakai?

SELECT INTO adalah perintah yang bikin tabel baru sekaligus mengisinya dengan hasil query dalam satu langkah. Struktur tabelnya dibentuk otomatis dari kolom yang kamu pilih. Perintah ini kepakai waktu kamu butuh nyimpen hasil sementara, bikin salinan data buat uji coba, atau nyiapin tabel staging buat laporan.

Bedanya sama INSERT INTO gampang diinget. SELECT INTO bikin tabel baru dan gagal kalau tabelnya udah ada. INSERT INTO nambahin baris ke tabel yang udah ada dan gagal kalau tabelnya belum ada.

KebutuhanPerintah
Bikin tabel baru dari hasil querySELECT INTO atau CREATE TABLE AS SELECT
Nambah baris ke tabel yang udah adaINSERT INTO ... SELECT
Nyimpen hasil sementara dalam satu queryCTE (WITH ...)
Nyimpen hasil biar bisa dipakai query lainTabel staging

Kalau hasil olahanmu cuma kepakai di dalam satu query, pakai CTE aja, jangan bikin tabel. Sintaksnya ada di tutorial Common Table Expression.

Gimana sintaks SELECT INTO di tiap database?

Sintaksnya beda-beda, dan ini sumber error nomor satu. SQL Server pakai SELECT INTO buat bikin tabel. PostgreSQL, MySQL, dan SQLite pakai CREATE TABLE AS SELECT. Di PostgreSQL, SELECT INTO masih ada tapi dokumentasi resminya menyarankan CREATE TABLE AS.

-- SQL Server
SELECT kolom1, kolom2
INTO tabel_baru
FROM tabel_sumber
WHERE kondisi;
-- PostgreSQL, MySQL, SQLite, Oracle
CREATE TABLE tabel_baru AS
SELECT kolom1, kolom2
FROM tabel_sumber
WHERE kondisi;
DatabaseBikin tabel dari queryCatatan
SQL ServerSELECT ... INTOSintaks utama, dipakai juga buat tabel sementara dengan awalan tanda pagar
PostgreSQLCREATE TABLE ASSELECT INTO jalan, tapi dokumentasinya menyarankan CREATE TABLE AS
MySQLCREATE TABLE ... AS SELECTSELECT INTO di MySQL dipakai buat variabel dan OUTFILE, bukan bikin tabel
OracleCREATE TABLE AS SELECTSELECT INTO di PL/SQL buat ngisi variabel
SQLiteCREATE TABLE AS SELECTNggak dukung SELECT INTO

Rincian klausanya di SQL Server ada di dokumentasi resmi Microsoft, sedangkan versi PostgreSQL bisa kamu cek di halaman CREATE TABLE AS di postgresql.org.

Apa itu tabel staging dan kenapa laporan bulanan butuh?

Tabel staging adalah tabel antara yang nampung hasil olahan setengah jadi, sebelum dipakai buat laporan akhir. Fungsinya motong kerjaan berulang. Query laporan bulanan biasanya nge-join banyak tabel dan ngitung agregat yang sama berkali-kali, dan tiap revisi kecil berarti nunggu dari awal lagi.

Alur yang paling umum kebagi tiga lapis:

  1. Lapis mentah. Data asli dari sistem operasional, nggak diubah sama sekali.
  2. Lapis staging. Data udah difilter, dibersihin, dan diagregasi ke satu tingkat kedetailan yang jelas.
  3. Lapis laporan. Query akhir yang tinggal ngambil dari staging, cepat dan gampang dibaca.

Ini pola ETL versi paling sederhana, dan bisa kamu jalanin di satu database tanpa tool tambahan.

Aturan yang bikin staging berguna: tiap tabel staging harus punya grain yang ditulis jelas. Satu baris di stg_penjualan_harian artinya satu tanggal per cabang, titik. Kalau grain-nya kabur, semua angka di lapis laporan jadi tebakan. Penjelasan lengkapnya ada di artikel grain tabel.

Gimana bikin tabel staging buat laporan bulanan?

Mulai dari satu tabel staging per sumber, dengan grain paling halus yang masih kamu butuhin. Filter periodenya di tahap ini, jangan di lapis laporan, biar volumenya kecil sejak awal.

-- Staging 1: penjualan harian per cabang
DROP TABLE IF EXISTS stg_penjualan_harian;

CREATE TABLE stg_penjualan_harian AS
SELECT
  CAST(t.tanggal AS date)        AS tanggal,
  t.cabang_id,
  COUNT(DISTINCT t.transaksi_id) AS jumlah_struk,
  SUM(t.total)                   AS omzet
FROM transaksi t
WHERE t.tanggal >= DATE '2025-08-01'
  AND t.tanggal <  DATE '2025-09-01'
  AND t.status = 'selesai'
GROUP BY CAST(t.tanggal AS date), t.cabang_id;

Perhatiin filter tanggalnya. Pola lebih besar sama dengan awal bulan dan lebih kecil dari awal bulan berikutnya itu aman buat kolom yang nyimpen jam, beda dengan BETWEEN yang bisa motong transaksi jam 23 lewat.

-- Staging 2: biaya harian per cabang
DROP TABLE IF EXISTS stg_biaya_harian;

CREATE TABLE stg_biaya_harian AS
SELECT
  CAST(b.tanggal AS date) AS tanggal,
  b.cabang_id,
  SUM(b.nominal)          AS total_biaya
FROM biaya_operasional b
WHERE b.tanggal >= DATE '2025-08-01'
  AND b.tanggal <  DATE '2025-09-01'
GROUP BY CAST(b.tanggal AS date), b.cabang_id;

Dua tabel staging ini sekarang punya grain yang sama persis: satu tanggal per cabang. Karena grainnya sama, join-nya aman dan nggak bikin baris keduplikat.

-- Lapis laporan: tinggal gabung, cepat dan gampang dibaca
SELECT
  p.tanggal,
  p.cabang_id,
  p.jumlah_struk,
  p.omzet,
  COALESCE(b.total_biaya, 0)                  AS total_biaya,
  p.omzet - COALESCE(b.total_biaya, 0)        AS laba_kotor
FROM stg_penjualan_harian p
LEFT JOIN stg_biaya_harian b
  ON  b.tanggal   = p.tanggal
  AND b.cabang_id = p.cabang_id
ORDER BY p.tanggal, p.cabang_id;

COALESCE di situ penting. Hari yang nggak ada biayanya bakal keluar NULL, dan NULL dikurangi apa pun hasilnya NULL.

Gimana bikin alurnya aman dijalankan berulang?

Query laporan bulanan bakal kamu jalanin lagi tiap bulan, dan sering diulang beberapa kali dalam satu bulan gara-gara data telat masuk. Jadi skripnya harus bisa dieksekusi berkali-kali dan hasilnya tetap sama. Sifat ini namanya idempoten.

Ada dua pola yang umum dipakai.

-- Pola 1: buang dan bikin ulang
DROP TABLE IF EXISTS stg_penjualan_harian;
CREATE TABLE stg_penjualan_harian AS SELECT ... ;
-- Pola 2: kosongkan lalu isi ulang, struktur tabel tetap
DELETE FROM stg_penjualan_harian
WHERE tanggal >= DATE '2025-08-01'
  AND tanggal <  DATE '2025-09-01';

INSERT INTO stg_penjualan_harian (tanggal, cabang_id, jumlah_struk, omzet)
SELECT ... ;

Pola pertama lebih simpel dan cocok buat tabel yang isinya cuma satu periode. Pola kedua lebih pas kalau tabel staging kamu nyimpen banyak bulan sekaligus, soalnya cuma bulan yang bersangkutan yang diganti.

Pola kedua juga bikin kamu bisa nambahin index dan constraint sekali di awal, dan itu nggak hilang tiap kali skripnya dijalanin.

Kalau databasemu dukung transaksi DDL, bungkus langkah hapus dan isi ulang dalam satu transaksi. Kalau prosesnya putus di tengah, datanya balik ke kondisi sebelumnya, bukan kosong separuh.

Contoh kasus: laporan bulanan toko_berkah

Toko_berkah itu dataset latihan ngulikdata berisi transaksi warung sembako di Semarang yang punya tiga cabang. Laporan bulanannya nge-join tabel transaksi, transaksi_item, produk, cabang, biaya_operasional, dan kalender hari libur.

Versi awalnya satu query panjang dengan enam join dan tiga subquery bersarang. Waktu jalannya 4 menit 20 detik di data Agustus.

Masalahnya bukan lambatnya doang. Tiap kali pemilik minta tambahan satu kolom, aku harus nunggu 4 menit lagi buat lihat hasilnya. Sepuluh kali revisi berarti 43 menit cuma buat nunggu.

Setelah dipecah jadi tiga tabel staging, waktu bangun stagingnya 51 detik dan query laporan akhirnya 4 detik. Total sekali jalan 55 detik, dan tiap revisi kolom cuma butuh 4 detik soalnya stagingnya nggak perlu dibangun ulang.

Penghematan yang lebih penting datang dari sisi lain. Waktu angka omzet di laporan beda sama catatan kasir, aku bisa langsung ngecek tabel stg_penjualan_harian tanpa nyari salahnya di dalam query 120 baris.

Ternyata penyebabnya transaksi berstatus batal yang ikut kehitung. Filter status di lapis staging nyelesaiin itu buat semua laporan turunannya sekaligus.

Kesalahan umum waktu pakai SELECT INTO dan staging

  1. Ngira index dan constraint ikut kesalin. Nggak. SELECT INTO cuma bawa kolom dan datanya. Primary key, index, dan default value harus kamu bikin lagi manual.
  2. Lupa kasih alias buat kolom hasil hitungan. Kolom hasil SUM tanpa alias bikin nama kolomnya nggak jelas atau bahkan error di sebagian database.
  3. Nggak filter periode di lapis staging. Kalau semua riwayat ikut masuk, staging-nya jadi sama beratnya dengan tabel asli.
  4. Tabel staging numpuk tanpa dibersihin. Kasih awalan nama yang seragam, misalnya stg_, dan bikin jadwal buat ngebuang yang udah nggak dipakai.
  5. Grain antar tabel staging beda. Satu per tanggal, satunya per transaksi. Begitu di-join, angkanya membengkak tanpa pesan error.
  6. Bikin tabel staging di database produksi tanpa izin. Tanya dulu ke pemilik database, dan taruh di skema terpisah kalau ada.
  7. Nggak ngecek jumlah baris setelah staging dibangun. Satu SELECT COUNT(*) sebelum dan sesudah nyelametin banyak laporan salah.

Kesalahan pertama yang paling mahal di database besar. Tabel staging tanpa index bikin query laporanmu jalan lambat, padahal tujuan awalnya biar cepat.

-- Tambahin index setelah tabel staging jadi
CREATE INDEX idx_stg_penjualan_tgl_cabang
  ON stg_penjualan_harian (tanggal, cabang_id);

Kalau sumber datamu punya baris kembar, bersihin di lapis staging, bukan di lapis laporan. Tekniknya ada di panduan menghapus data duplikat di SQL, dan hasilnya langsung kepakai buat semua laporan turunan. Ini juga bagian dari nge-jaga data quality tanpa nambah kerjaan berulang.

FAQ

Apa bedanya tabel staging sama view?

View nyimpen definisi query, bukan datanya, jadi tiap kali dipanggil query-nya dijalanin ulang dari awal. Tabel staging nyimpen hasilnya beneran, jadi query berikutnya tinggal baca. Kalau sumbernya berat dan hasilnya dipakai berkali-kali, tabel staging lebih hemat. Kalau datanya harus selalu terbaru, view lebih pas.

SELECT INTO bisa bikin tabel sementara?

Di SQL Server bisa, tinggal kasih awalan tanda pagar pada nama tabelnya, dan tabelnya otomatis hilang begitu koneksi ditutup. Di PostgreSQL kamu pakai CREATE TEMP TABLE AS SELECT. Tabel sementara cocok buat langkah antara yang cuma kepakai dalam satu sesi, misalnya waktu kamu lagi nelusuri selisih angka.

Kenapa SELECT INTO di PostgreSQL kadang error?

Biasanya karena kamu nulisnya di dalam blok PL/pgSQL. Di konteks itu, SELECT INTO artinya ngisi variabel, bukan bikin tabel. Buat bikin tabel dari hasil query, pakai CREATE TABLE AS SELECT. Dokumentasi PostgreSQL sendiri menyarankan CREATE TABLE AS supaya nggak ketuker dengan pemakaian di prosedur.

Berapa lapis staging yang ideal buat laporan bulanan?

Dua sampai tiga lapis biasanya cukup: mentah, staging, laporan. Lebih dari itu bikin alurnya susah ditelusuri kalau ada angka yang salah. Patokan yang aku pakai, tiap lapis harus bisa dijelasin dalam satu kalimat. Kalau kamu nggak bisa nyebut isi satu lapis dalam satu kalimat, lapis itu kebanyakan kerjaan.

Perlu bikin tabel staging kalau datanya cuma ribuan baris?

Biasanya nggak. Di data kecil, CTE atau subquery udah cukup dan lebih gampang dirawat karena semuanya ada di satu file query. Staging mulai kerasa manfaatnya waktu query-mu udah lewat 30 detik, atau waktu hasil olahan yang sama dipakai oleh lebih dari satu laporan.

Ringkasan dan langkah berikutnya

Tiga hal yang perlu kamu bawa:

  • SELECT INTO cuma sintaks SQL Server. Di PostgreSQL, MySQL, dan SQLite pakai CREATE TABLE AS SELECT.
  • Tulis grain tiap tabel staging dalam satu kalimat sebelum nulis query-nya.
  • Bikin skripnya idempoten pakai DROP TABLE IF EXISTS atau hapus per periode, biar aman dijalanin ulang.

Mau langsung nyoba bikin tabel staging dan ngecek grainnya di data transaksi beneran? Latihannya ada di NgulikSQL, jalan di browser tanpa install apa-apa.

Coba Langsung

Mau praktek langsung? Mulai latihan SQL gratis

Latihan interaktif, langsung di browser.

Buka NgulikSQL →
Bagikan:
Bima
Ditulis oleh

Bima

Founder & Data Professional

Founder Ngulik Data. Passionate about making data analysis accessible for everyone.

Artikel terkait

Cara Membuat Pivot Dinamis di SQL (Panduan 2026)
Tutorial SQL
19 Juli 2026•10 menit baca

Cara Membuat Pivot Dinamis di SQL (Panduan 2026)

Pivot dinamis di SQL ngubah baris jadi kolom tanpa kamu hardcode nama kolomnya. Ini cara bikinnya pakai CASE WHEN dan versi yang kolomnya ngikut data.

BimaBima
Menghitung YTD, QTD, dan MTD di SQL (Panduan 2026)
Tutorial SQL
17 Juli 2026•9 menit baca

Menghitung YTD, QTD, dan MTD di SQL (Panduan 2026)

YTD, QTD, dan MTD ngukur total dari awal tahun, kuartal, atau bulan sampai hari ini. Ini cara ngitungnya di SQL pakai DATE_TRUNC, plus satu query gabungan.

BimaBima
Gap and Island Analysis di SQL
Tutorial SQL
15 Juli 2026•10 menit baca

Gap and Island Analysis di SQL

Gap and island analysis di SQL nyari deret data yang berturut-turut (island) dan celah yang bolong (gap). Cocok buat hitung streak login atau cari tanggal transaksi yang hilang.

BimaBima
Kembali ke Blog
Ngulik Data logoNgulik Data

Platform edukasi data lengkap untuk professionals Indonesia. Belajar SQL, Data Analysis, dan lebih banyak lagi dengan praktek langsung dan feedback real-time.

© 2026 Ngulik Data. Semua hak dilindungi.

TAUTAN
BantuanHargaDatasetBlogAfiliasi
LEGAL
Syarat & KetentuanKebijakan Privasi
Ngulik Data
DatasetLeaderboardBlogStore