0Pricing
SQL Academy · Pelajaran

DISTINCT ON PostgreSQL

Pilih satu baris untuk setiap grup.

DISTINCT ON PostgreSQL adalah pelajaran SQL Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar SQL Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus SQL Academy mencakup 4 pelajaran total.

Apa Itu DISTINCT ON?

PostgreSQL menawarkan ekstensi andal untuk kata kunci DISTINCT standar yang disebut DISTINCT ON. Jika DISTINCT biasa menghapus baris yang sepenuhnya duplikat, DISTINCT ON memungkinkan Anda memilih tepat satu baris per kelompok berdasarkan satu atau beberapa kolom pilihan Anda.

Bayangkan seperti ini: 'Untuk setiap nilai unik dalam kolom ini, berikan satu baris.' Fitur ini sangat berguna saat Anda ingin mendapatkan pesanan terbaru untuk setiap pelanggan, skor tertinggi untuk setiap siswa, atau peristiwa pertama untuk setiap kategori.

Sintaks Dasar DISTINCT ON

Sintaksnya menempatkan DISTINCT ON (column) tepat setelah SELECT. Kolom di dalam tanda kurung menentukan pengelompokan — PostgreSQL akan mengembalikan satu baris untuk setiap nilai unik dari kolom tersebut.

Contoh di bawah mengembalikan satu baris untuk setiap customer_id dari tabel pesanan. PostgreSQL memilih baris yang akan dikembalikan berdasarkan klausa ORDER BY yang mengikutinya.

SELECT DISTINCT ON (customer_id)
  customer_id,
  order_id,
  order_date,
  total_amount
FROM orders
ORDER BY customer_id, order_date DESC;

Menyiapkan Tabel Contoh

Mari kita buat tabel orders sederhana dan masukkan beberapa baris contoh agar kita dapat mencoba DISTINCT ON secara langsung. Kita memiliki tiga pelanggan, masing-masing dengan beberapa pesanan pada tanggal yang berbeda.

CREATE TABLE orders (
  order_id      SERIAL PRIMARY KEY,
  customer_id   INT,
  order_date    DATE,
  total_amount  NUMERIC(10, 2)
);

INSERT INTO orders (customer_id, order_date, total_amount) VALUES
  (1, '2024-01-05', 120.00),
  (1, '2024-03-12', 85.50),
  (1, '2024-06-20', 200.00),
  (2, '2024-02-14', 45.00),
  (2, '2024-05-30', 310.00),
  (3, '2024-04-01', 75.00);

Pesanan Terbaru per Pelanggan

Kasus penggunaan yang sangat umum: temukan pesanan paling baru untuk setiap pelanggan. Dengan mengurutkan order_date DESC dalam setiap kelompok customer_id, DISTINCT ON memilih baris dengan tanggal terbaru.

Perhatikan bahwa klausa ORDER BY harus dimulai dengan kolom yang sama seperti yang dicantumkan dalam DISTINCT ON. Ini merupakan persyaratan PostgreSQL.

SELECT DISTINCT ON (customer_id)
  customer_id,
  order_id,
  order_date,
  total_amount
FROM orders
ORDER BY customer_id, order_date DESC;

Pesanan Paling Awal per Pelanggan

Untuk mendapatkan pesanan pertama (paling lama) dari setiap pelanggan, cukup ubah arah pengurutan menjadi ASC. Satu-satunya perbedaan adalah urutan baris dalam setiap kelompok — DISTINCT ON selalu memilih baris pertama setelah pengurutan.

SELECT DISTINCT ON (customer_id)
  customer_id,
  order_id,
  order_date,
  total_amount
FROM orders
ORDER BY customer_id, order_date ASC;

Aturan ORDER BY

Aturan penting: Saat menggunakan DISTINCT ON (col), klausa ORDER BY harus dimulai dengan kolom yang sama seperti yang dicantumkan di dalam DISTINCT ON. Jika tidak, PostgreSQL akan menghasilkan kesalahan.

Setelah kolom pengelompokan, Anda dapat menambahkan kriteria pengurutan lain untuk mengatur baris mana dalam setiap kelompok yang dipilih.

-- Correct: ORDER BY starts with the DISTINCT ON column
SELECT DISTINCT ON (customer_id)
  customer_id, order_date, total_amount
FROM orders
ORDER BY customer_id, total_amount DESC;

-- This would cause an error:
-- ORDER BY order_date DESC  (missing customer_id at the start)

Skor Tertinggi per Siswa

Berikut contoh praktis lainnya menggunakan tabel test_scores. Kita ingin mengetahui skor tertinggi yang pernah dicapai setiap siswa. Dengan mengurutkan score DESC dalam setiap kelompok siswa, DISTINCT ON hanya mengembalikan baris dengan skor tertinggi untuk setiap siswa.

CREATE TABLE test_scores (
  id         SERIAL PRIMARY KEY,
  student_id INT,
  subject    VARCHAR(50),
  score      INT,
  taken_on   DATE
);

INSERT INTO test_scores (student_id, subject, score, taken_on) VALUES
  (101, 'Math',    92, '2024-02-10'),
  (101, 'Math',    78, '2024-04-15'),
  (102, 'Math',    85, '2024-02-10'),
  (102, 'Math',    91, '2024-04-15'),
  (103, 'Math',    67, '2024-02-10');

SELECT DISTINCT ON (student_id)
  student_id, subject, score, taken_on
FROM test_scores
ORDER BY student_id, score DESC;

DISTINCT ON dengan Beberapa Kolom

Anda dapat mengelompokkan berdasarkan lebih dari satu kolom dengan mencantumkan beberapa kolom di dalam DISTINCT ON. Cara ini mengembalikan satu baris untuk setiap kombinasi unik dari kolom-kolom tersebut.

Contoh di bawah memilih skor tertinggi untuk setiap siswa pada setiap mata pelajaran, dengan memperlakukan setiap pasangan (siswa, mata pelajaran) sebagai kelompoknya sendiri.

INSERT INTO test_scores (student_id, subject, score, taken_on) VALUES
  (101, 'Science', 88, '2024-03-01'),
  (101, 'Science', 95, '2024-05-20'),
  (102, 'Science', 72, '2024-03-01');

SELECT DISTINCT ON (student_id, subject)
  student_id, subject, score, taken_on
FROM test_scores
ORDER BY student_id, subject, score DESC;

Menyaring dengan WHERE

DISTINCT ON bekerja secara alami bersama klausa WHERE. Penyaringan diterapkan terlebih dahulu, lalu DISTINCT ON memilih satu baris per kelompok dari hasil yang telah disaring.

Di sini kita mencari pesanan terbaru untuk setiap pelanggan, tetapi hanya untuk pesanan dengan nilai di atas 100.

SELECT DISTINCT ON (customer_id)
  customer_id,
  order_id,
  order_date,
  total_amount
FROM orders
WHERE total_amount > 100
ORDER BY customer_id, order_date DESC;

DISTINCT ON vs GROUP BY

DISTINCT ON dan GROUP BY sama-sama dapat menghasilkan satu baris per kelompok, tetapi keduanya memiliki tujuan yang berbeda:

  • GROUP BY meringkas baris dan memerlukan fungsi agregat (SUM, MAX, dan sebagainya) untuk kolom yang tidak dikelompokkan.
  • DISTINCT ON mempertahankan baris nyata yang sudah ada — semua kolomnya tersedia tanpa agregasi.

Gunakan GROUP BY saat Anda memerlukan nilai agregat. Gunakan DISTINCT ON saat Anda memerlukan seluruh data dari baris tertentu dalam setiap kelompok.

-- GROUP BY: only aggregated columns allowed
SELECT customer_id, MAX(order_date) AS latest_date
FROM orders
GROUP BY customer_id;

-- DISTINCT ON: returns the whole row for that latest date
SELECT DISTINCT ON (customer_id)
  customer_id, order_id, order_date, total_amount
FROM orders
ORDER BY customer_id, order_date DESC;

Menggunakan DISTINCT ON dalam Subkueri

Terkadang Anda perlu menerapkan penyaringan atau pengurutan lebih lanjut pada hasil DISTINCT ON. Karena ORDER BY di kueri luar terikat pada kolom pengelompokan, Anda dapat membungkus kueri tersebut dalam subkueri (atau CTE) untuk menerapkan pengurutan yang berbeda pada keluaran akhir.

Contoh ini terlebih dahulu memilih pesanan terbaru untuk setiap pelanggan, lalu mengurutkan hasil akhir berdasarkan total_amount secara menurun.

SELECT *
FROM (
  SELECT DISTINCT ON (customer_id)
    customer_id,
    order_id,
    order_date,
    total_amount
  FROM orders
  ORDER BY customer_id, order_date DESC
) AS latest_orders
ORDER BY total_amount DESC;

Pemeriksaan Cepat

Mari kita periksa pemahaman Anda tentang DISTINCT ON. Bacalah kueri di bawah dengan saksama dan pilih jawaban yang paling tepat menjelaskan apa yang dikembalikannya.

SELECT DISTINCT ON (department_id) department_id, employee_name, salary FROM employees ORDER BY department_id, salary DESC;

Ringkasan Pelajaran

Kerja bagus! Berikut ringkasan hal-hal yang telah Anda pelajari tentang PostgreSQL DISTINCT ON:

  • DISTINCT ON (col) mengembalikan tepat satu baris untuk setiap nilai unik dari kolom yang ditentukan.
  • Klausa ORDER BY harus dimulai dengan kolom yang sama seperti yang dicantumkan dalam DISTINCT ON — klausa ini menentukan baris mana yang dipilih dari setiap kelompok.
  • Anda dapat menggunakan beberapa kolom: DISTINCT ON (col1, col2) mengelompokkan berdasarkan kombinasi keduanya.
  • Berbeda dari GROUP BY, DISTINCT ON mengembalikan baris nyata dengan semua kolom aslinya — tidak diperlukan agregasi.
  • Bungkus kueri dalam subkueri jika Anda perlu mengurutkan keluaran akhir berdasarkan kolom yang berbeda.

DISTINCT ON merupakan fitur khusus PostgreSQL dan salah satu cara paling elegan untuk menyelesaikan masalah 'pilih satu baris per kelompok'.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “DISTINCT ON PostgreSQL” gratis?

Ya — teks lengkap “DISTINCT ON PostgreSQL” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus SQL Academy, upgrade ke CoddyKit PRO. Kursus SQL Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “DISTINCT ON PostgreSQL”?

Pilih satu baris untuk setiap grup. Kamu berlatih SQL Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai SQL Academy?

Tidak diperlukan pengalaman sebelumnya. SQL Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.

Berapa lama pelajaran “DISTINCT ON PostgreSQL” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran SQL Academy ini?

Ya. Setiap pelajaran SQL Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Dasar-Dasar SELECT DISTINCT
  2. DISTINCT pada Beberapa Kolom
  3. DISTINCT ON PostgreSQL
  4. Menghitung Nilai Unik
← Kembali ke SQL Academy