在列上使用distinct并在另一列上执行order by会产生错误

pra*_*pta 11 sql oracle distinct sql-order-by oracle9i

我有一个表:abc_test,列n_num,k_str.

此查询不起作用:

    select distinct(n_num) from abc_test order by(k_str)
Run Code Online (Sandbox Code Playgroud)

但是这个有效:

    select n_num from abc_test order by(k_str)
Run Code Online (Sandbox Code Playgroud)

DISTINCT和ORDER BY关键字如何在内部工作,以改变两个查询的输出?

Abh*_*ari 12

据我所知,你的问题.

distinct: - 表示选择不同的(所有选定的值应该是唯一的).order by: - 只是意味着根据您的要求对所选行进行排序.

第一个查询中的问题是例如:我有一个表

ID name
01 a
02 b
03 c
04 d 
04 a
Run Code Online (Sandbox Code Playgroud)

现在查询select distinct(ID) from table order by (name)混淆了它应该为ID-04采取哪个记录(因为有两个值,d和a在Name列中).因此,当您说(名称)时,数据库引擎的问题就在这里.........


Flo*_*ita 5

第一个查询是不可能的。让我们通过例子来解释这一点。我们有这个测试:

n_num k_str
2     a
2     c
1     b
Run Code Online (Sandbox Code Playgroud)

select distinct (n_num) from abc_test

2
1
Run Code Online (Sandbox Code Playgroud)

Select n_num from abc_test order by k_str

2
1
2
Run Code Online (Sandbox Code Playgroud)

你想返回什么

select distinct (n_num) from abc_test order by k_str?

它应该只返回 1 和 2,但如何订购它们?


Nil*_*nde 5

您可能会考虑改为使用分组依据:

select n_num
from abc_test
group by n_num
order by min(k_str)
Run Code Online (Sandbox Code Playgroud)


Luk*_*der 5

如何对键列进行扩展排序

第一个查询的SQL 操作的逻辑顺序是(简化的):

  • FROM abc_test
  • SELECT n_num, k_str即添加一个所谓的扩展排序键列
  • ORDER BY k_str DESC
  • SELECT n_num即再次从结果中删除扩展排序键列。

由于 SQL 标准扩展排序键列功能,可以按子句中没有的内容进行排序SELECT,因为它在排序之前在幕后临时添加到子句中,然后在排序后再次删除。

那么,为什么这不起作用DISTINCT

如果我们添加DISTINCT操作,则需要在SELECT和之间添加ORDER BY

  • FROM abc_test
  • SELECT n_num, k_str即添加一个所谓的扩展排序键列
  • DISTINCT
  • ORDER BY k_str DESC
  • SELECT n_num即再次从结果中删除扩展排序键列。

但现在,随着扩展的排序键列 k_str,操作的语义DISTINCT已经改变,因此结果将不再相同。这不是我们想要的,因此 SQL 标准和所有合理的数据库都禁止这种用法。

解决方法

PostgreSQL 有这样的DISTINCT ON语法,可以在这里使用它来完成这项工作:

SELECT DISTINCT ON (k_str) n_num
FROM abc_test
ORDER BY k_str DESC
Run Code Online (Sandbox Code Playgroud)

如果您不使用 PostgreSQL,可以使用标准语法进行模拟,如下所示

SELECT n_num
FROM (
  SELECT n_num, MIN(k_str) AS k_str
  FROM abc_test
  GROUP BY n_num
) t
ORDER BY k_str
Run Code Online (Sandbox Code Playgroud)

或者,只是简单地(在本例中)

SELECT n_num, MIN(k_str) AS k_str
FROM abc_test
GROUP BY n_num
ORDER BY k_str
Run Code Online (Sandbox Code Playgroud)

我在博客中更详细地介绍了 SQL DISTINCT 和 ORDER BY