0Pricing
SQL Academy · Leçon

DISTINCT ON de PostgreSQL

Sélectionnez une ligne par groupe.

DISTINCT ON de PostgreSQL est une leçon SQL Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage SQL Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours SQL Academy comprend 4 leçons au total.

Qu'est-ce que DISTINCT ON ?

PostgreSQL propose une extension puissante du mot-clé standard DISTINCT, appelée DISTINCT ON. Alors que DISTINCT classique supprime les lignes entièrement dupliquées, DISTINCT ON vous permet de sélectionner exactement une ligne par groupe en fonction d'une ou plusieurs colonnes de votre choix.

Considérez-le ainsi : « Pour chaque valeur unique de cette colonne, donnez-moi une ligne. » Cette fonctionnalité est extrêmement utile lorsque vous voulez obtenir la commande la plus récente par client, le score le plus élevé par étudiant ou le premier événement par catégorie.

Syntaxe de base de DISTINCT ON

La syntaxe place DISTINCT ON (column) juste après SELECT. La colonne entre parenthèses définit le regroupement — PostgreSQL renvoie une ligne pour chaque valeur unique de cette colonne.

L'exemple ci-dessous renvoie une ligne par customer_id depuis une table de commandes. PostgreSQL choisit la ligne à renvoyer en fonction de la clause ORDER BY qui suit.

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

Mise en place des tables d'exemple

Créons une table orders simple et insérons quelques lignes d'exemple afin d'essayer DISTINCT ON en pratique. Nous avons trois clients, chacun ayant plusieurs commandes à des dates différentes.

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

Commande la plus récente par client

Un cas d'utilisation très courant consiste à trouver la commande la plus récente de chaque client. En triant order_date DESC dans chaque groupe customer_id, DISTINCT ON sélectionne la ligne dont la date est la plus récente.

Remarquez que la clause ORDER BY doit commencer par la ou les mêmes colonnes que celles indiquées dans DISTINCT ON. Il s'agit d'une exigence de PostgreSQL.

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

Commande la plus ancienne par client

Pour obtenir plutôt la première commande (la plus ancienne) de chaque client, il suffit de remplacer le sens du tri par ASC. La seule différence concerne l'ordre des lignes au sein de chaque groupe — DISTINCT ON sélectionne toujours la première ligne après le tri.

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

Règle de ORDER BY

Règle importante : lors de l'utilisation de DISTINCT ON (col), la clause ORDER BY doit commencer par la ou les mêmes colonnes que celles indiquées dans DISTINCT ON. Si ce n'est pas le cas, PostgreSQL génère une erreur.

Après la ou les colonnes de regroupement, vous pouvez ajouter n'importe quels critères de tri supplémentaires afin de contrôler la ligne sélectionnée dans chaque groupe.

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

Score le plus élevé par étudiant

Voici un autre exemple pratique utilisant une table test_scores. Nous voulons obtenir le score le plus élevé jamais obtenu par chaque étudiant. En triant score DESC dans le groupe de chaque étudiant, DISTINCT ON renvoie uniquement la ligne ayant le score le plus élevé pour chaque étudiant.

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 avec plusieurs colonnes

Vous pouvez regrouper selon plusieurs colonnes en indiquant plusieurs colonnes dans DISTINCT ON. Cela renvoie une ligne pour chaque combinaison unique de ces colonnes.

L'exemple ci-dessous sélectionne le score le plus élevé pour chaque étudiant et pour chaque matière, en traitant chaque paire (étudiant, matière) comme son propre groupe.

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;

Filtrer avec WHERE

DISTINCT ON fonctionne naturellement avec les clauses WHERE. Le filtre est appliqué en premier, puis DISTINCT ON sélectionne une ligne par groupe à partir des résultats filtrés.

Ici, nous trouvons la commande la plus récente par client, mais uniquement parmi les commandes supérieures à 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 ou GROUP BY

DISTINCT ON et GROUP BY peuvent tous deux produire une ligne par groupe, mais ils ont des rôles différents :

  • GROUP BY regroupe les lignes et nécessite des fonctions d'agrégation (SUM, MAX, etc.) pour les colonnes qui ne font pas partie du regroupement.
  • DISTINCT ON conserve une ligne réellement existante — toutes ses colonnes sont disponibles sans agrégation.

Utilisez GROUP BY lorsque vous avez besoin de valeurs agrégées. Utilisez DISTINCT ON lorsque vous avez besoin de toutes les données d'une ligne précise au sein de chaque groupe.

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

Utiliser DISTINCT ON dans une sous-requête

Il vous faut parfois appliquer un filtrage ou un tri supplémentaire au résultat de DISTINCT ON. Comme le ORDER BY externe est lié à la colonne de regroupement, vous pouvez encapsuler la requête dans une sous-requête (ou une CTE) afin d'appliquer un tri différent à la sortie finale.

Cet exemple sélectionne d'abord la commande la plus récente par client, puis trie le résultat final par total_amount par ordre décroissant.

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;

Vérification rapide

Vérifions votre compréhension de DISTINCT ON. Lisez attentivement la requête ci-dessous et choisissez la réponse qui décrit le mieux ce qu'elle renvoie.

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

Récapitulatif de la leçon

Excellent travail ! Voici un résumé de ce que vous avez appris sur PostgreSQL DISTINCT ON :

  • DISTINCT ON (col) renvoie exactement une ligne par valeur unique de la ou des colonnes spécifiées.
  • La clause ORDER BY doit commencer par la ou les mêmes colonnes que celles indiquées dans DISTINCT ON — elle détermine la ligne sélectionnée dans chaque groupe.
  • Vous pouvez utiliser plusieurs colonnes : DISTINCT ON (col1, col2) regroupe selon leur combinaison.
  • Contrairement à GROUP BY, DISTINCT ON renvoie une ligne réelle avec toutes ses colonnes d'origine — aucune agrégation n'est nécessaire.
  • Encapsulez la requête dans une sous-requête lorsque vous devez trier la sortie finale selon une autre colonne.

DISTINCT ON est une fonctionnalité propre à PostgreSQL et l'un des moyens les plus élégants de résoudre les problèmes consistant à « sélectionner une ligne par groupe ».

Questions Fréquemment Posées

La leçon « DISTINCT ON de PostgreSQL » est-elle gratuite ?

Oui — le texte complet de « DISTINCT ON de PostgreSQL » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours SQL Academy, passe à CoddyKit PRO. Le cours SQL Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « DISTINCT ON de PostgreSQL » ?

Sélectionnez une ligne par groupe. Tu pratiques SQL Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer SQL Academy ?

Aucune expérience préalable n'est requise. SQL Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.

Combien de temps prend la leçon « DISTINCT ON de PostgreSQL » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon SQL Academy ?

Oui. Chaque leçon SQL Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Principes de SELECT DISTINCT
  2. DISTINCT sur plusieurs colonnes
  3. DISTINCT ON de PostgreSQL
  4. Compter les valeurs uniques
← Retour à SQL Academy