web-dev-qa-db-fra.com

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

Après avoir exécuté l'instruction 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 enlever les doublons, comme ceci:

bildung
test4
test3
test2
test1

J'ai essayé d'utiliser DISTINCT mais cela ne fonctionne pas avec ORDER BY en une seule déclaration. S'il vous plaît aider.

Important:

  1. Je l'ai essayé avec:

    SELECT DISTINCT Category FROM MonitoringJob ORDER BY CreationDate DESC
    

    ça ne marche pas.

  2. Order by CreationDate est très important.

84
r.r

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

Essayez quelque chose comme ça:

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

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. Par conséquent, l'instruction dans la réponse de Prutswonder n'est pas utilisable dans ce cas. Vous ne pouvez pas placer de sélection externe autour d'elle et ignorer la partie MAX (CreationDate).

4
Marc_Sei

Colonnes de tri étendues

La raison pour laquelle ce que vous voulez faire ne fonctionne pas est due à la ordre logique des opérations en SQL , qui, pour votre première requête, est (simplifiée):

  • FROM MonitoringJob
  • SELECT Category, CreationDate c'est-à-dire ajouter une colonne de clé de tri étendue
  • ORDER BY CreationDate DESC
  • SELECT Category c’est-à-dire supprimer à nouveau la colonne de clé de tri extended du résultat.

Ainsi, grâce à la fonctionnalité standard extended tri colonne de la clé de tri [], il est tout à fait possible d'ordonner quelque chose qui ne figure pas dans la clause SELECT, car elle y est temporairement ajoutée en arrière-plan.

Alors, pourquoi cela ne fonctionne-t-il pas avec DISTINCT?

Si nous ajoutons l'opération DISTINCT, elle serait ajoutée entre SELECT et ORDER BY:

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

Mais maintenant, avec la colonne de clé de tri extendedCreationDate, la sémantique de l'opération 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, aussi bien le standard SQL que toutes les bases de données raisonnables interdisent cet usage.

Solutions de contournement

PostgreSQL a la syntaxe DISTINCT ON, qui peut être utilisée ici précisément pour ce travail:

SELECT DISTINCT ON (CreationDate) Category 
FROM MonitoringJob 
ORDER BY CreationDate DESC

Il peut être émulé avec la syntaxe standard comme suit

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 indiqué également par Prutswonder

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

_ { J'ai blogué sur SQL DISTINCT et ORDER BY de manière plus détaillée ici }.

4
Lukas Eder

Utilisez simplement ce code, si vous voulez les valeurs des colonnes [Category] et [CreationDate]

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

Ou utilisez ce code, si vous souhaitez uniquement 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.

2
Prashant Gupta

2) Order by CreationDate est très important

Les résultats originaux indiquaient que "test3" avait plusieurs résultats ...

Il est très facile de commencer à utiliser MAX tout le temps pour supprimer les doublons de Group By ... et oublier ou ignorer la question sous-jacente ... 

L’opérateur s’est probablement rendu compte que l’utilisation de MAX lui donnait le dernier "créé" et que l’utilisation de MIN donnerait le premier "créé" ...

1
JohnSurrey
if object_id ('tempdb..#tempreport') is not null
begin  
drop table #tempreport
end 
create table #tempreport (
Category  nvarchar(510),
CreationDate smallint )
insert into #tempreport 
select distinct Category from MonitoringJob (nolock) 
select * from #tempreport  ORDER BY CreationDate DESC
0
Bob

Distinct triera les enregistrements par ordre croissant. Si vous voulez trier par ordre décroissant, utilisez:

SELECT DISTINCT Category
FROM MonitoringJob
ORDER BY Category DESC

Si vous souhaitez trier les enregistrements en fonction du champ CreationDate, ce champ doit figurer dans l'instruction select:

SELECT DISTINCT Category, creationDate
FROM MonitoringJob
ORDER BY CreationDate DESC
0
C Patel

En sous-requête, cela devrait fonctionner:

    SELECT distinct(Category) from MonitoringJob  where Category in(select Category from MonitoringJob order by CreationDate desc);
0

Vous pouvez utiliser CTE:

WITH DistinctMonitoringJob AS (
    SELECT DISTINCT Category Distinct_Category FROM MonitoringJob 
)

SELECT Distinct_Category 
FROM DistinctMonitoringJob 
ORDER BY Distinct_Category DESC
0
Jair