Как использовать DISTINCT и ORDER BY в одном выражении SELECT?

После выполнения следующего оператора:

SELECT  Category  FROM MonitoringJob ORDER BY CreationDate DESC

Я получаю следующие значения из базы данных:

test3
test3
bildung
test4
test3
test2
test1

но я хочу, чтобы дубликаты были удалены, например:

bildung
test4
test3
test2
test1

Я попытался использовать DISTINCT, но он не работает с ORDER BY в одном выражении. Пожалуйста, помогите.

Важно:

  • Я попробовал:

    SELECT DISTINCT Category FROM MonitoringJob ORDER BY CreationDate DESC
    

    он не работает.

  • Заказ by CreationDate очень важен.

Ответ 1

Проблема в том, что столбцы, используемые в ORDER BY, не указаны в DISTINCT. Чтобы сделать это, вам нужно использовать агрегатную функцию для сортировки и использовать GROUP BY чтобы заставить DISTINCT работать.

Попробуйте что-то вроде этого:

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

Ответ 2

Расширенные столбцы ключей сортировки

Причина, по которой вы не хотите работать, заключается в логическом порядке операций в SQL, который для вашего первого запроса (упрощен):

  • FROM MonitoringJob
  • SELECT Category, CreationDate т.е. добавить так называемый расширенный столбец ключа сортировки
  • ORDER BY CreationDate DESC
  • SELECT Category т.е. снова удалите расширенный столбец ключа сортировки из результата.

Таким образом, благодаря стандартной функции расширенного столбца ключа сортировки SQL, можно полностью упорядочить что-то, чего нет в предложении SELECT, потому что оно временно добавляется к нему за кулисами.

Итак, почему это не работает с DISTINCT?

Если мы добавим операцию DISTINCT, она будет добавлена между SELECT и ORDER BY:

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

Но теперь, с расширенным столбцом ключа сортировки CreationDate, семантика операции DISTINCT была изменена, поэтому результат больше не будет прежним. Это не то, что мы хотим, поэтому и стандарт SQL, и все разумные базы данных запрещают это использование.

обходные

Его можно эмулировать со стандартным синтаксисом следующим образом

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

Или просто (в данном случае), как показано Prutswonder

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

Я более подробно писал о SQL DISTINCT и ORDER BY здесь.

Ответ 3

Если вывод MAX (CreationDate) не нужен - как в примере исходного вопроса - единственный ответ - это второй оператор ответа Прашанта Гупта:

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

Объяснение: вы не можете использовать предложение ORDER BY в встроенной функции, поэтому утверждение в ответе Prutswonder в этом случае невозможно использовать, вы не можете поместить внешний выбор вокруг него и отменить MAX (CreationDate ) часть.

Ответ 4

Просто используйте этот код. Если вам нужны значения столбцов [Категория] и [CreationDate]

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

Или используйте этот код, если вы хотите только значения столбца [Категория].

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

У вас будут все записи, которые вы хотите.

Ответ 5

2) Заказ by CreationDate очень важен

Исходные результаты показали, что "test3" имеет несколько результатов...

Очень легко начать использовать MAX все время, чтобы удалить дубликаты в Group By... и забыть или игнорировать то, что основной вопрос...

OP предположительно осознал, что использование MAX дало ему последний "созданный", и использование MIN дало бы первый "созданный"...

Ответ 6

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

Ответ 7

По подзапросу должно работать:

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

Ответ 8

Distinct будет сортировать записи в порядке возрастания. Если вы хотите отсортировать в порядке desc, используйте:

SELECT DISTINCT Category
FROM MonitoringJob
ORDER BY Category DESC

Если вы хотите отсортировать записи на основе поля CreationDate, это поле должно быть в инструкции select:

SELECT DISTINCT Category, creationDate
FROM MonitoringJob
ORDER BY CreationDate DESC

Ответ 9

Вы можете использовать CTE:

WITH DistinctMonitoringJob AS (
    SELECT DISTINCT Category Distinct_Category FROM MonitoringJob 
)

SELECT Distinct_Category 
FROM DistinctMonitoringJob 
ORDER BY Distinct_Category DESC

Ответ 10

Попробуйте следующее, но это не полезно для огромных данных...

SELECT DISTINCT Cat FROM (
  SELECT Category as Cat FROM MonitoringJob ORDER BY CreationDate DESC
);

Ответ 11

Это можно сделать, используя внутренний запрос. Как этот

$query = "SELECT * 
            FROM (SELECT Category  
                FROM currency_rates                 
                ORDER BY id DESC) as rows               
            GROUP BY currency";

Ответ 12

SELECT DISTINCT Category FROM MonitoringJob ORDER BY Category ASC