如何在同一个SELECT语句中使用DISTINCT和ORDER BY?

r.r*_*r.r 97 sql distinct sql-order-by

执行以下语句后:

SELECT  Category  FROM MonitoringJob ORDER BY CreationDate DESC
Run Code Online (Sandbox Code Playgroud)

我从数据库中获取以下值:

test3
test3
bildung
test4
test3
test2
test1
Run Code Online (Sandbox Code Playgroud)

但我希望删除重复项,如下所示:

bildung
test4
test3
test2
test1
Run Code Online (Sandbox Code Playgroud)

我尝试使用DISTINCT,但它在一个语句中不能与ORDER BY一起使用.请帮忙.

重要:

  1. 我尝试过:

    SELECT DISTINCT Category FROM MonitoringJob ORDER BY CreationDate DESC
    
    Run Code Online (Sandbox Code Playgroud)

    它不起作用.

  2. CreationDate的订单非常重要.

Pru*_*der 167

问题是在ORDER BY中未指定列中使用的列DISTINCT.为此,您需要使用聚合函数进行排序,并使用a GROUP BY来完成DISTINCT工作.

尝试这样的事情:

SELECT DISTINCT Category, MAX(CreationDate) 
FROM MonitoringJob 
GROUP BY Category 
ORDER BY MAX(CreationDate) DESC, Category
Run Code Online (Sandbox Code Playgroud)

  • 如果按类别进行分组,则甚至不需要DISTINCT关键字. (82认同)
  • 为了解释为什么你需要一个聚合函数(在你的 ORDER BY 中,不一定在你的 SELECT 中!),我找到了一篇简洁的文章:https://weblogs.sqlteam.com/jeffs/2007/12/13/select -distinct-order-by-error/ TLDR:当对 GROUP BY 之后的每一行使用 MIN() 或 MAX() 时,它会获取组中的最高或最低值。 (2认同)

Luk*_*der 11

扩展排序键列

您要执行的操作不起作用的原因是由于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
Run Code Online (Sandbox Code Playgroud)

或者,只是简单地(在这种情况下),如Prutswonder所示

SELECT Category, MAX(CreationDate) AS CreationDate
FROM MonitoringJob
GROUP BY Category
ORDER BY CreationDate DESC
Run Code Online (Sandbox Code Playgroud)

我在这里已详细介绍了SQL DISTINCT和ORDER BY。


Mar*_*Sei 6

如果不需要 MAX(CreationDate) 的输出 - 就像在原始问题的示例中一样 - 唯一的答案是 Prashant Gupta 答案的第二个陈述:

SELECT [Category] FROM [MonitoringJob] 
GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC
Run Code Online (Sandbox Code Playgroud)

说明:你不能在内联函数中使用 ORDER BY 子句,所以在这种情况下,Prutswonder 的答案中的语句是不可用的,你不能在它周围放置一个外部选择并丢弃 MAX(CreationDate) 部分。


小智 5

如果您想要 [Category] ​​和 [CreationDate] 列的值,只需使用此代码

SELECT [Category], MAX([CreationDate]) FROM [MonitoringJob] 
             GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC
Run Code Online (Sandbox Code Playgroud)

或者,如果您只需要 [Category] ​​列的值,请使用此代码。

SELECT [Category] FROM [MonitoringJob] 
GROUP BY [Category] ORDER BY MAX([CreationDate]) DESC
Run Code Online (Sandbox Code Playgroud)

您将拥有您想要的所有不同记录。

  • 括号用于转义关键字,例如 Order、event 等。因此,如果您的表中有(例如)名为“Event”的列,您可以编写“[Event]”而不是“Event”来阻止 SQL 抛出异常解析错误。 (2认同)