¿Cómo usar DISTINCT y ORDER BY en la misma instrucción SELECT?


Después de ejecutar la siguiente instrucción:

SELECT  Category  FROM MonitoringJob ORDER BY CreationDate DESC

Estoy obteniendo los siguientes valores de la base de datos:

test3
test3
bildung
test4
test3
test2
test1

Pero quiero que se eliminen los duplicados, así:

bildung
test4
test3
test2
test1

Traté de usar DISTINCT pero no funciona con ORDER BY en una declaración. Por favor, ayuda.

Importante:

  1. Lo probé con:

    SELECT DISTINCT Category FROM MonitoringJob ORDER BY CreationDate DESC
    

    No funciona.

  2. Ordenar por fecha de creación es muy importante.

Author: Pang, 2011-03-22

11 answers

El problema es que las columnas utilizadas en el ORDER BY no se especifican en el DISTINCT. Para hacer esto, necesita usar una función aggregate para ordenar, y usar un GROUP BY para hacer que el DISTINCT funcione.

Intenta algo como esto:

SELECT DISTINCT Category, MAX(CreationDate) 
FROM MonitoringJob 
GROUP BY Category 
ORDER BY MAX(CreationDate) DESC, Category
 138
Author: Prutswonder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-28 15:48:04

Si la salida de MAX(creationDate) no es deseada - como en el ejemplo de la pregunta original-la única respuesta es la segunda declaración de la respuesta de Prashant Gupta:

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

Explicación: no se puede usar la cláusula ORDER BY en una función en línea, por lo que la instrucción en la respuesta de Prutswonder no se puede usar en este caso, no se puede poner una selección externa alrededor de ella y descartar la parte MAX(creationDate).

 4
Author: Marc_Sei,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-16 21:29:37

Simplemente use este código, si desea valores de las columnas [Category] y [creationDate]

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

O use este código, si solo desea valores de la columna [Categoría].

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

Tendrás todos los registros distintos lo que quieras.

 2
Author: Prashant Gupta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-30 06:46:01

Columnas de clave de ordenación extendidas

La razón por la que lo que quieres hacer no funciona es debido al orden lógico de las operaciones en SQL , que, para tu primera consulta, es (simplificado):

  • FROM MonitoringJob
  • SELECT Category, CreationDate es decir, agregar una llamada columna de clave de ordenación extendida
  • ORDER BY CreationDate DESC
  • SELECT Category es decir, eliminar la columna extended sort key de nuevo del resultado.

Así que, gracias al estándar SQL extended sort key columna característica, es totalmente posible ordenar por algo que no está en la cláusula SELECT, porque se está agregando temporalmente a ella detrás de las escenas.

Entonces, ¿por qué esto no funciona con DISTINCT?

Si añadimos la operación DISTINCT, se añadiría entre SELECT y ORDER BY:

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

Pero ahora, con la columna de clave de ordenación extendida CreationDate, la semántica de la operación DISTINCT se ha cambiado, por lo que el resultado ya no será el mismo. Esto no es lo que queremos, por lo que tanto el estándar SQL como todas las bases de datos razonables prohíben este uso.

Soluciones alternativas

PostgreSQL tiene la sintaxis DISTINCT ON, que se puede usar aquí precisamente para este trabajo:

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

Se puede emular con sintaxis estándar de la siguiente manera

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

O, simplemente (en este caso), como se muestra también por Prutswonder

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

Tengo blogueado sobre SQL DISTINTO y ORDEN POR más en detalle aquí .

 2
Author: Lukas Eder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-20 08:24:07

2) Ordenar por fecha de creación es muy importante

Los resultados originales indicaban que "test3" tenía múltiples resultados...

Es muy fácil comenzar a usar MAX todo el tiempo para eliminar duplicados en Grupos By... y olvidar o ignorar cuál es la pregunta subyacente...

El OP presumiblemente se dio cuenta de que usar MAX le estaba dando el último "creado" y usar MIN le daría el primer "creado"...

 1
Author: JohnSurrey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-22 10:08:36

Distinct ordenará los registros en orden ascendente. Si desea ordenar en orden desc utilice:

SELECT DISTINCT Category
FROM MonitoringJob
ORDER BY Category DESC

Si desea ordenar registros basados en el campo creationDate, este campo debe estar en la instrucción select:

SELECT DISTINCT Category, creationDate
FROM MonitoringJob
ORDER BY CreationDate DESC
 0
Author: C Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-27 11:36:05
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
Author: Bob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-25 14:11:00

Puedes usar CTE:

WITH DistinctMonitoringJob AS (
    SELECT DISTINCT Category Distinct_Category FROM MonitoringJob 
)

SELECT Distinct_Category 
FROM DistinctMonitoringJob 
ORDER BY Distinct_Category DESC
 0
Author: Jair,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-10 18:53:38

Pruebe a continuación, pero no es útil para datos enormes...

SELECT DISTINCT Cat FROM (
  SELECT Category as Cat FROM MonitoringJob ORDER BY CreationDate DESC
);
 -2
Author: Máťa - Stitod.cz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-18 13:16:16

Se puede hacer usando una consulta interna Como esta

$query = "SELECT * 
            FROM (SELECT Category  
                FROM currency_rates                 
                ORDER BY id DESC) as rows               
            GROUP BY currency";
 -3
Author: Zaheer Babar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-25 15:35:31
SELECT DISTINCT Category FROM MonitoringJob ORDER BY Category ASC
 -4
Author: Furicane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-22 12:56:42