0Pricing
SQL Academy · Lektion

PostgreSQL DISTINCT ON

Eine Zeile pro Gruppe auswählen

PostgreSQL DISTINCT ON ist eine kostenlose SQL Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des SQL Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der SQL Academy-Kurs umfasst insgesamt 4 Lektionen.

Was ist DISTINCT ON?

PostgreSQL bietet eine leistungsstarke Erweiterung des standardmäßigen Schlüsselworts DISTINCT namens DISTINCT ON. Während das normale DISTINCT vollständig doppelte Zeilen entfernt, können Sie mit DISTINCT ON anhand einer oder mehrerer ausgewählter Spalten genau eine Zeile pro Gruppe auswählen.

Stellen Sie es sich so vor: „Geben Sie mir für jeden eindeutigen Wert in dieser Spalte eine Zeile.“ Das ist äußerst nützlich, wenn Sie die neueste Bestellung pro Kunden, die höchste Punktzahl pro Lernendem oder das erste Ereignis pro Kategorie benötigen.

Grundlegende DISTINCT-ON-Syntax

Die Syntax platziert DISTINCT ON (column) direkt hinter SELECT. Die Spalte in den Klammern definiert die Gruppierung: PostgreSQL gibt für jeden eindeutigen Wert dieser Spalte eine Zeile zurück.

Das folgende Beispiel gibt aus einer orders-Tabelle eine Zeile pro customer_id zurück. Welche Zeile ausgewählt wird, bestimmt PostgreSQL anhand der folgenden ORDER BY-Klausel.

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

Beispieltabellen erstellen

Erstellen Sie eine einfache orders-Tabelle und fügen Sie einige Beispielzeilen ein, damit Sie DISTINCT ON praktisch ausprobieren können. Es gibt drei Kunden, die jeweils mehrere Bestellungen an unterschiedlichen Tagen aufgegeben haben.

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);

Neueste Bestellung pro Kunde

Ein sehr häufiger Anwendungsfall: Finden Sie die neueste Bestellung für jeden Kunden. Wenn Sie innerhalb jeder customer_id-Gruppe nach order_date DESC sortieren, wählt DISTINCT ON die Zeile mit dem neuesten Datum aus.

Beachten Sie, dass die ORDER BY-Klausel mit derselben Spalte bzw. denselben Spalten beginnen muss, die in DISTINCT ON aufgeführt sind. Dies ist eine Anforderung von PostgreSQL.

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

Älteste Bestellung pro Kunde

Um stattdessen die erste (älteste) Bestellung pro Kunde zu erhalten, ändern Sie einfach die Sortierrichtung in ASC. Der einzige Unterschied ist die Reihenfolge der Zeilen innerhalb jeder Gruppe: DISTINCT ON wählt immer die erste Zeile nach der Sortierung aus.

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

Die ORDER-BY-Regel

Wichtige Regel: Bei der Verwendung von DISTINCT ON (col) muss die ORDER BY-Klausel mit derselben Spalte bzw. denselben Spalten beginnen, die innerhalb von DISTINCT ON aufgeführt sind. Andernfalls gibt PostgreSQL einen Fehler aus.

Nach den Gruppierungsspalten können Sie beliebige zusätzliche Sortierkriterien hinzufügen, um zu steuern, welche Zeile innerhalb jeder Gruppe ausgewählt wird.

-- 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)

Höchste Punktzahl pro Lernendem

Hier ist ein weiteres praktisches Beispiel mit einer test_scores-Tabelle. Wir möchten die höchste Punktzahl ermitteln, die jeder Lernende jemals erreicht hat. Wenn Sie innerhalb jeder Lerngruppe nach score DESC sortieren, gibt DISTINCT ON nur die Zeile mit der höchsten Punktzahl pro Lernendem zurück.

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 mit mehreren Spalten

Sie können nach mehr als einer Spalte gruppieren, indem Sie mehrere Spalten in DISTINCT ON aufführen. Dadurch wird eine Zeile für jede eindeutige Kombination dieser Spalten zurückgegeben.

Das folgende Beispiel wählt die höchste Punktzahl pro Lernendem und Fach aus und behandelt jedes Paar aus (Lernender, Fach) als eigene Gruppe.

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;

Mit WHERE filtern

DISTINCT ON lässt sich problemlos zusammen mit WHERE-Klauseln verwenden. Der Filter wird zuerst angewendet. Anschließend wählt DISTINCT ON aus den gefilterten Ergebnissen eine Zeile pro Gruppe aus.

Hier ermitteln wir die neueste Bestellung pro Kunde, berücksichtigen aber nur Bestellungen über 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

Sowohl DISTINCT ON als auch GROUP BY können eine Zeile pro Gruppe erzeugen, dienen aber unterschiedlichen Zwecken:

  • GROUP BY fasst Zeilen zusammen und erfordert für nicht gruppierte Spalten Aggregatfunktionen (SUM, MAX usw.).
  • DISTINCT ON behält eine tatsächlich vorhandene Zeile bei – alle ihre Spalten sind ohne Aggregation verfügbar.

Verwenden Sie GROUP BY, wenn Sie aggregierte Werte benötigen. Verwenden Sie DISTINCT ON, wenn Sie die vollständigen Daten einer bestimmten Zeile innerhalb jeder Gruppe benötigen.

-- 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;

DISTINCT ON in einer Unterabfrage verwenden

Manchmal müssen Sie das Ergebnis von DISTINCT ON zusätzlich filtern oder sortieren. Da das äußere ORDER BY an die Gruppierungsspalte gebunden ist, können Sie die Abfrage in eine Unterabfrage (oder CTE) einschließen, um eine andere Sortierung auf die endgültige Ausgabe anzuwenden.

In diesem Beispiel wird zunächst die neueste Bestellung pro Kunde ausgewählt. Anschließend wird das endgültige Ergebnis absteigend nach total_amount sortiert.

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;

Kurzer Test

Überprüfen Sie Ihr Verständnis von DISTINCT ON. Lesen Sie die folgende Abfrage sorgfältig und wählen Sie die Antwort aus, die am besten beschreibt, was sie zurückgibt.

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

Zusammenfassung der Lektion

Sehr gute Arbeit! Hier ist eine Zusammenfassung dessen, was Sie über PostgreSQL DISTINCT ON gelernt haben:

  • DISTINCT ON (col) gibt genau eine Zeile pro eindeutigem Wert der angegebenen Spalte bzw. Spalten zurück.
  • Die ORDER BY-Klausel muss mit derselben Spalte bzw. denselben Spalten beginnen, die in DISTINCT ON aufgeführt sind. Sie bestimmt, welche Zeile aus jeder Gruppe ausgewählt wird.
  • Sie können mehrere Spalten verwenden: DISTINCT ON (col1, col2) gruppiert nach der Kombination aus beiden Spalten.
  • Im Gegensatz zu GROUP BY gibt DISTINCT ON eine echte Zeile mit allen ursprünglichen Spalten zurück – eine Aggregation ist nicht erforderlich.
  • Schließen Sie die Abfrage in eine Unterabfrage ein, wenn Sie die endgültige Ausgabe nach einer anderen Spalte sortieren müssen.

DISTINCT ON ist eine PostgreSQL-spezifische Funktion und eine der elegantesten Möglichkeiten, Probleme nach dem Muster „eine Zeile pro Gruppe auswählen“ zu lösen.

Häufig gestellte Fragen

Ist die Lektion „PostgreSQL DISTINCT ON“ kostenlos?

Ja — der vollständige Text von „PostgreSQL DISTINCT ON“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des SQL Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der SQL Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „PostgreSQL DISTINCT ON“?

Eine Zeile pro Gruppe auswählen Du übst SQL Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um SQL Academy zu starten?

Keine Vorkenntnisse erforderlich. SQL Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.

Wie lange dauert die Lektion „PostgreSQL DISTINCT ON“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser SQL Academy-Lektion Code schreiben und ausführen?

Ja. Jede SQL Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Grundlagen von SELECT DISTINCT
  2. DISTINCT für mehrere Spalten
  3. PostgreSQL DISTINCT ON
  4. Eindeutige Werte zählen
← Zurück zu SQL Academy