151 votes

Comment utiliser DISTINCT et ORDER BY dans la même instruction SELECT ?

Après avoir exécuté la déclaration suivante :

SELECT  Category  FROM MonitoringJob ORDER BY CreationDate DESC

Je reçois les valeurs suivantes de la base de données :

test3
test3
bildung
test4
test3
test2
test1

mais je veux que les doublons soient supprimés, comme ceci :

bildung
test4
test3
test2
test1

J'ai essayé d'utiliser DISTINCT mais cela ne fonctionne pas avec ORDER BY dans une déclaration. Merci de m'aider.

Important :

  1. J'ai essayé avec :

    SELECT DISTINCT Category FROM MonitoringJob ORDER BY CreationDate DESC

    cela ne fonctionne pas.

  2. L'ordre par date de création est très important.

261voto

Prutswonder Points 5146

Le problème est que les colonnes utilisées dans le ORDER BY ne sont pas spécifiés dans le DISTINCT . Pour ce faire, vous devez utiliser un fonction agrégée pour effectuer un tri, et utiliser un GROUP BY pour faire de la DISTINCT travail.

Essayez quelque chose comme ceci :

SELECT DISTINCT Category, MAX(CreationDate) 
FROM MonitoringJob 
GROUP BY Category 
ORDER BY MAX(CreationDate) DESC, Category

37voto

Lukas Eder Points 48046

Colonnes clés de tri étendues

La raison pour laquelle ce que vous voulez faire ne fonctionne pas est due à la l'ordre logique des opérations en SQL, comme je l'ai expliqué dans cet article du blog ce qui, pour votre première question, est (simplifié) :

  • FROM MonitoringJob
  • SELECT Category, CreationDate c'est-à-dire ajouter un soi-disant colonne clé de tri étendue
  • ORDER BY CreationDate DESC
  • SELECT Category c'est-à-dire supprimer le colonne clé de tri étendue à partir du résultat.

Ainsi, grâce à la norme SQL colonne clé de tri étendue Il est tout à fait possible de commander par un élément qui n'est pas dans la liste. SELECT parce qu'elle lui est temporairement ajoutée en coulisses.

Pourquoi cela ne fonctionne-t-il pas avec DISTINCT ?

Si nous ajoutons le DISTINCT l'opération, il serait ajouté entre SELECT y ORDER BY :

  • FROM MonitoringJob
  • SELECT Category, CreationDate
  • DISTINCT
  • ORDER BY CreationDate DESC
  • SELECT Category

Mais aujourd'hui, avec la colonne clé de tri étendue CreationDate , la sémantique de la DISTINCT a été modifiée, de sorte que le résultat ne sera plus le même. Ce n'est pas ce que nous voulons, c'est pourquoi la norme SQL et toutes les bases de données raisonnables interdisent cette utilisation.

Solutions de rechange

Il peut être émulé avec la syntaxe standard suivante

SELECT Category
FROM (
  SELECT Category, MAX(CreationDate) AS CreationDate
  FROM MonitoringJob
  GROUP BY Category
) t
ORDER BY CreationDate DESC

Ou, tout simplement (dans ce cas), comme le montrent également les exemples suivants Prutswonder

SELECT Category, MAX(CreationDate) AS CreationDate
FROM MonitoringJob
GROUP BY Category
ORDER BY CreationDate DESC

J'ai fait un blog sur SQL DISTINCT et ORDER BY plus en détail ici. .

9voto

Marc_Sei Points 51

Si la sortie de MAX(CreationDate) n'est pas souhaitée - comme dans l'exemple de la question initiale - la seule réponse est la deuxième affirmation de la réponse de Prashant Gupta :

SELECT [Category] FROM [MonitoringJob] 
GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC

Explication : vous ne pouvez pas utiliser la clause ORDER BY dans une fonction en ligne, donc la déclaration dans la réponse de Prutswonder n'est pas utilisable dans ce cas, vous ne pouvez pas l'entourer d'une sélection externe et ignorer la partie MAX(CreationDate).

5voto

Prashant Gupta Points 53

Il suffit d'utiliser ce code, si vous souhaitez obtenir les valeurs des colonnes [Catégorie] et [Date de création].

SELECT [Category], MAX([CreationDate]) FROM [MonitoringJob] 
             GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC

Ou utilisez ce code, si vous ne voulez que les valeurs de la colonne [Catégorie].

SELECT [Category] FROM [MonitoringJob] 
GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC

Vous aurez tous les enregistrements distincts que vous voulez.

2voto

JohnSurrey Points 36

2) L'ordre par CreationDate est très important

Les résultats originaux indiquaient que "test3" avait des résultats multiples...

Il est très facile d'utiliser MAX en permanence pour supprimer les doublons dans les groupes... et d'oublier ou d'ignorer la question sous-jacente...

L'OP a vraisemblablement réalisé que l'utilisation de MAX lui donnait le dernier "créé" et que l'utilisation de MIN lui donnait le premier "créé"...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X