SQL Pratique
DISTINCT en SQL : supprimer les doublons efficacement
8 min de lecture

DISTINCT en SQL : supprimer les doublons efficacement

Maîtrisez DISTINCT en SQL pour éliminer les doublons. Syntaxe, pièges, performances et alternatives expliqués avec exemples concrets.

Avatar de Thomas LeroyThomas Leroy

SELECT DISTINCT est l'une des clauses SQL les plus utilisées pour éliminer les lignes dupliquées d'un résultat. En entretien technique comme en production, savoir l'utiliser correctement — et surtout savoir quand ne pas l'utiliser — fait toute la différence. Cet article couvre la syntaxe complète, les cas d'usage réels, les pièges de performance, et les alternatives souvent plus efficaces. Que vous soyez data analyst ou développeur, vous repartirez avec une vision claire de la déduplication en SQL.

📌 Ce qu'il faut retenir

  • DISTINCT s'applique à toutes les colonnes du SELECT, pas seulement la première
  • Il peut fortement impacter les performances sur de gros volumes de données
  • GROUP BY est souvent une alternative plus lisible et plus contrôlable
  • En entretien, on attend que vous connaissiez ses limites, pas seulement sa syntaxe

La syntaxe de base de DISTINCT

La forme la plus simple s'écrit ainsi :

SELECT DISTINCT colonne
FROM ma_table;

Si vous listez plusieurs colonnes, DISTINCT s'applique à la combinaison de toutes ces colonnes, pas à chacune indépendamment :

SELECT DISTINCT pays, ville
FROM clients;

Cette requête renvoie chaque paire (pays, ville) unique. Elle ne renvoie pas les villes uniques par pays. C'est l'erreur la plus fréquente que l'on voit en entretien : confondre "distinct sur une colonne" et "distinct sur plusieurs colonnes".

⚠️ Attention

Il est impossible d'écrire SELECT colonne1, DISTINCT colonne2. DISTINCT se place immédiatement après SELECT et s'applique à toute la liste de colonnes. Toute autre syntaxe génère une erreur.

Pourquoi des doublons apparaissent-ils ?

Avant de supprimer des doublons, comprendre leur origine est essentiel. Les sources les plus courantes sont :

  • Jointures mal maîtrisées : un JOIN sur une table avec plusieurs lignes correspondantes multiplie les résultats
  • Données sources mal nettoyées : imports CSV, pipelines ETL qui insèrent plusieurs fois la même donnée
  • Absence de contraintes d'unicité : une table sans PRIMARY KEY ni UNIQUE peut contenir des lignes identiques
  • Agrégations partielles : oublier une colonne dans le GROUP BY peut produire des pseudo-doublons

Identifier la cause du doublon vous indique si DISTINCT est la bonne solution — ou si le problème se trouve en amont dans le modèle de données. C'est une distinction que les recruteurs apprécient particulièrement lors des tests techniques SQL.

DISTINCT avec COUNT et les agrégats

DISTINCT peut s'utiliser à l'intérieur des fonctions d'agrégat, ce qui est très courant en analyse de données :

SELECT COUNT(DISTINCT client_id) AS clients_uniques
FROM commandes;

Cette requête compte le nombre de clients différents ayant passé au moins une commande, et non le nombre total de lignes. Comparez :

-- Nombre total de commandes
SELECT COUNT(client_id) FROM commandes;        -- ex: 15 000

-- Nombre de clients distincts
SELECT COUNT(DISTINCT client_id) FROM commandes; -- ex: 4 200

Ce type de requête est omniprésent dans les dashboards analytiques. On l'utilise pour calculer des métriques comme le nombre d'utilisateurs actifs, le nombre de produits commandés, ou le reach d'une campagne marketing.

Vous pouvez également combiner plusieurs agrégats distincts dans la même requête :

SELECT
  COUNT(DISTINCT client_id)  AS clients_uniques,
  COUNT(DISTINCT produit_id) AS produits_distincts,
  SUM(montant)               AS chiffre_affaires
FROM commandes
WHERE date_commande >= '2026-01-01';

Pour aller plus loin sur les fonctions d'agrégat, consultez notre guide sur les fonctions d'agrégat SQL : SUM, COUNT, AVG, MIN, MAX.

Impact sur les performances : ce que vous devez savoir

DISTINCT déclenche une opération de tri ou de hachage en interne pour identifier les doublons. Sur de grandes tables, cela peut devenir coûteux. Voici un tableau comparatif des approches de déduplication :

Méthode Lisibilité Performance Cas d'usage idéal
SELECT DISTINCT Très simple Moyenne (tri complet) Petits volumes, exploration rapide
GROUP BY Lisible Bonne (optimisable) Déduplication avec agrégats
ROW_NUMBER() Verbeuse Excellente (avec index) Garder une ligne parmi N doublons
Sous-requête + EXISTS Complexe Variable Filtres conditionnels avancés
CTE + déduplication Excellente Bonne Pipelines de transformation de données

💡 Bon à savoir

Sur PostgreSQL et BigQuery, l'optimiseur peut parfois réécrire un SELECT DISTINCT en GROUP BY en interne. Mais ne comptez pas sur ce comportement : écrivez explicitement ce que vous souhaitez pour garantir la lisibilité et la maintenabilité de votre code.

GROUP BY comme alternative à DISTINCT

Dans de nombreux cas, GROUP BY produit le même résultat que DISTINCT, avec l'avantage de pouvoir ajouter des agrégats :

-- Équivalent avec DISTINCT
SELECT DISTINCT pays, ville FROM clients;

-- Équivalent avec GROUP BY
SELECT pays, ville FROM clients GROUP BY pays, ville;

Les 2 requêtes renvoient les mêmes lignes. La version GROUP BY devient cependant indispensable dès que vous voulez ajouter une information agrégée :

SELECT pays, ville, COUNT(*) AS nb_clients
FROM clients
GROUP BY pays, ville
ORDER BY nb_clients DESC;

Avec DISTINCT, cette requête serait impossible à écrire de façon directe. GROUP BY est donc la solution naturelle dès que la déduplication s'accompagne d'un calcul.

ROW_NUMBER() pour une déduplication avancée

Quand vous avez plusieurs doublons et souhaitez garder une ligne spécifique (la plus récente, la plus élevée, etc.), ROW_NUMBER() est bien plus puissant que DISTINCT :

WITH dedup AS (
  SELECT *,
    ROW_NUMBER() OVER (
      PARTITION BY client_id
      ORDER BY date_commande DESC
    ) AS rn
  FROM commandes
)
SELECT *
FROM dedup
WHERE rn = 1;

Cette requête conserve la commande la plus récente par client, ce qu'il est impossible d'exprimer avec un simple SELECT DISTINCT. C'est typiquement le genre de question posée dans les entretiens techniques pour évaluer votre maîtrise des fonctions fenêtre.

Pour approfondir ROW_NUMBER() et ses variantes, l'article RANK, DENSE_RANK et ROW_NUMBER en SQL détaille toutes les nuances.

DISTINCT ON : la spécificité PostgreSQL

PostgreSQL propose une syntaxe étendue appelée DISTINCT ON, qui n'existe pas dans MySQL ou SQL Server :

SELECT DISTINCT ON (client_id)
  client_id,
  date_commande,
  montant
FROM commandes
ORDER BY client_id, date_commande DESC;

Cette syntaxe garde une seule ligne par client_id, en appliquant l'ordre défini dans ORDER BY. C'est une syntaxe très pratique pour la déduplication ciblée sur une colonne précise, tout en conservant les autres colonnes de la ligne sélectionnée.

Elle n'est cependant pas portable vers d'autres bases de données. En entretien, mentionner cette spécificité montre une bonne culture des dialectes SQL.

Questions fréquentes

DISTINCT ralentit-il toujours les requêtes ?

Pas systématiquement, mais il introduit toujours un coût supplémentaire. Sur de petites tables ou des colonnes indexées, l'impact est négligeable. Sur des tables de plusieurs millions de lignes sans index adapté, le tri nécessaire à la déduplication peut multiplier le temps d'exécution par 5 à 10. Il est conseillé de vérifier le plan d'exécution avec EXPLAIN avant de déployer en production.

Peut-on utiliser DISTINCT avec ORDER BY ?

Oui, mais avec une contrainte : les colonnes dans ORDER BY doivent apparaître dans la liste SELECT. En cas contraire, la base de données ne peut pas trier des colonnes qui n'ont pas été sélectionnées après déduplication. La règle est logique : on ne peut pas ordonner quelque chose qu'on n'a pas gardé.

DISTINCT gère-t-il les valeurs NULL ?

Oui. En SQL, NULL est traité comme une valeur distincte unique. Si une colonne contient 3 lignes avec NULL, SELECT DISTINCT ne retournera qu'une seule ligne NULL. C'est cohérent avec la logique de déduplication, mais il faut le savoir pour éviter les surprises dans vos analyses.

Quelle est la différence entre DISTINCT et UNIQUE ?

UNIQUE est une contrainte sur une colonne ou un ensemble de colonnes, définie au niveau du schéma de table. DISTINCT est un mot-clé de requête qui filtre les résultats en lecture seule. Ils adressent 2 problèmes différents : l'un empêche les doublons à l'insertion, l'autre les supprime à l'affichage.

DISTINCT fonctionne-t-il avec les sous-requêtes ?

Oui, on peut utiliser DISTINCT aussi bien dans la requête principale que dans une sous-requête. Cela dit, dans une sous-requête utilisée avec IN ou EXISTS, DISTINCT est souvent inutile car ces opérateurs travaillent déjà sur des ensembles de valeurs. L'ajouter ne provoque pas d'erreur, mais ne change pas le résultat.

Conclusion

SELECT DISTINCT est un outil simple et puissant pour l'exploration rapide de données et l'élimination de doublons évidents. Mais comme tout outil SQL, il a ses limites : il s'applique à toutes les colonnes, peut peser sur les performances, et ne permet pas de choisir quelle ligne garder parmi les doublons. Connaître ses alternatives — GROUP BY, ROW_NUMBER(), DISTINCT ON — vous rend bien plus efficace en production et plus convaincant en entretien.

Entraînez-vous sur des cas concrets pour ancrer ces notions. La plateforme SQL Pratique propose des exercices interactifs avec correction détaillée pour pratiquer DISTINCT et toutes les techniques de déduplication dans un environnement d'exécution en ligne.

Prêt à vous entraîner ?

50 exercices SQL interactifs avec éditeur en ligne, chronomètre et feedback IA.

Voir les exercices