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

发布于 2024-12-27 17:08:41 字数 287 浏览 2 评论 0原文

我有一张桌子: abc_test 包含 n_num、k_str 列。

此查询不起作用:

    select distinct(n_num) from abc_test order by(k_str)

但是这个查询有效:

    select n_num from abc_test order by(k_str)

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

I have a table:
abc_test with columns n_num, k_str.

This query doesnt work:

    select distinct(n_num) from abc_test order by(k_str)

But this one works:

    select n_num from abc_test order by(k_str)

How do DISTINCT and ORDER BY keywords work internally that output of both the queries is changed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

漫雪独思 2025-01-03 17:08:41

据我从你的问题中了解到。

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

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

ID name
01 a
02 b
03 c
04 d 
04 a

,查询 select unique(ID) from table order by (name) 混淆了 ID - 04 应该采用哪个记录(因为名称列中有两个值,d 和 a) )。所以当你说时数据库引擎的问题就在这里
按(姓名)订购......

As far as i understood from your question .

distinct :- means select a distinct(all selected values should be unique).
order By :- simply means to order the selected rows as per your requirement .

The problem in your first query is
For example :
I have a table

ID name
01 a
02 b
03 c
04 d 
04 a

now the query select distinct(ID) from table order by (name) is confused which record it should take for ID - 04 (since two values are there,d and a in Name column). So the problem for the DB engine is here when you say
order by (name).........

情栀口红 2025-01-03 17:08:41

您可能会考虑使用 group by 来代替:

select n_num
from abc_test
group by n_num
order by min(k_str)

You might think about using group by instead:

select n_num
from abc_test
group by n_num
order by min(k_str)
枕头说它不想醒 2025-01-03 17:08:41

扩展排序键列如何

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

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

感谢 SQL 标准扩展排序键列功能,可以按 SELECT 子句中没有的内容进行排序,因为它被临时添加到 SELECT 子句后面订购前的场景,订购后再次删除。

那么,为什么这不适用于 DISTINCT 呢?

如果我们添加DISTINCT操作,则需要在SELECTORDER BY之间添加:

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

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

解决方法

PostgreSQL 具有 DISTINCT ON 语法,可以在此处准确地使用该语法:

SELECT DISTINCT ON (k_str) n_num
FROM abc_test
ORDER BY k_str DESC

如果您不使用 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

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

SELECT n_num, MIN(k_str) AS k_str
FROM abc_test
GROUP BY n_num
ORDER BY k_str

我写过关于 SQL 的博客DISTINCT 和 ORDER BY 的更多详细信息请参见此处

How do extended sort key columns

The logical order of operations in SQL for your first query, is (simplified):

  • FROM abc_test
  • SELECT n_num, k_str i.e. add a so called extended sort key column
  • ORDER BY k_str DESC
  • SELECT n_num i.e. remove the extended sort key column again from the result.

Thanks to the SQL standard extended sort key column feature, it is possible to order by something that is not in the SELECT clause, because it is being temporarily added to it behind the scenes prior to ordering, and then removed again after ordering.

So, why doesn't this work with DISTINCT?

If we add the DISTINCT operation, it would need to be added between SELECT and ORDER BY:

  • FROM abc_test
  • SELECT n_num, k_str i.e. add a so called extended sort key column
  • DISTINCT
  • ORDER BY k_str DESC
  • SELECT n_num i.e. remove the extended sort key column again from the result.

But now, with the extended sort key column k_str, the semantics of the DISTINCT operation has been changed, so the result will no longer be the same. This is not what we want, so both the SQL standard, and all reasonable databases forbid this usage.

Workarounds

PostgreSQL has the DISTINCT ON syntax, which can be used here for precisely this job:

SELECT DISTINCT ON (k_str) n_num
FROM abc_test
ORDER BY k_str DESC

It can be emulated with standard syntax as follows, if you're not using 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

Or, just simply (in this case)

SELECT n_num, MIN(k_str) AS k_str
FROM abc_test
GROUP BY n_num
ORDER BY k_str

I have blogged about SQL DISTINCT and ORDER BY more in detail here.

月牙弯弯 2025-01-03 17:08:41

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

n_num k_str
2     a
2     c
1     b

select different (n_num) from abc_test

2
1

Select n_num from abc_test order by k_str

2
1
2

你想要返回什么

select different (n_num) from abc_test 按 k_str 排序

它应该只返回 1 和 2,但是如何对它们进行排序呢?

The first query is impossible.
Lets explain this by example. we have this test:

n_num k_str
2     a
2     c
1     b

select distinct (n_num) from abc_test is

2
1

Select n_num from abc_test order by k_str is

2
1
2

What do you want to return

select distinct (n_num) from abc_test order by k_str?

it should return only 1 and 2, but how to order them?

花伊自在美 2025-01-03 17:08:41

您正在从查询的结果集中选择集合distinct(n_num)。因此与 k_str 列不再有实际关系。 n_num 可以来自两行,每行具有不同的 k_str 值。所以你不能通过k_str对集合进行distinct(n_num)排序。

You are selecting the collection distinct(n_num) from the resultset from your query. So there is no actual relation with the column k_str anymore. A n_num can be from two rows each having a different value for k_str. So you can't order the collection distinct(n_num) by k_str.

孤蝉 2025-01-03 17:08:41

根据 SQL 标准,SELECT 子句可以引用顶级 SELECT 子句中的 as 子句(“别名”),也可以按序号位置引用结果集的列,因此您的查询均不符合要求。

看来 Oracle 与其他 SQL 实现一样,允许您引用在 SELECT 子句中投影之前(逻辑上)存在的列。我不确定这种灵活性是否是一件好事:IMO 通过在 SELECT 子句中包含列/表达式等来向调用应用程序公开排序顺序是一种很好的做法。

与以往一样,您需要应用 dsicpline 才能获得有意义的结果。对于您的第一个查询,顺序的定义可能完全是任意的。您应该对这个错误表示感谢;)

According to SQL Standards, a SELECT clause may refer either to as clauses ("aliases") in the top level SELECT clause or columns of the resultset by ordinal position, and therefore nether of your queries would be compliant.

It seems Oracle, in common with other SQL implemetations, allows you to refer to columns that existed (logically) immediately prior to being projected away in the SELECT clause. I'm not sure whether such flexibility is such a good thing: IMO it is good practice to expose the sort order to the calling application by including the column/expressions etc in the SELECT clause.

As ever, you need to apply dsicpline to get meaningful results. For your first query, the definition of order is potentially entirely arbitrary.You should be grateful for the error ;)

打小就很酷 2025-01-03 17:08:41

这种方法在 SQL Server 2000 中可用,您可以从表中选择不同的值,并按不包含在 Distinct 中的不同列进行排序。
但在 SQL 2012 中这会告诉你一个错误
“如果指定了 SELECT DISTINCT,则 ORDER BY 项必须出现在选择列表中。”

因此,如果您想使用与 SQL 2000 相同的功能,您可以使用列号进行排序(最佳实践中不推荐)。

select distinct(n_num) from abc_test order by 1

这将在获取结果后对第一列进行排序。如果您希望排序应基于不同的列而不是不同的列来完成,那么您还必须在 select 语句中添加该列并使用列号进行排序。

select distinct(n_num), k_str from abc_test order by 2

This approach is available in SQL server 2000, you can select distinct values from a table and order by different column which is not included in Distinct.
But in SQL 2012 this will through you an error
"ORDER BY items must appear in the select list if SELECT DISTINCT is specified."

So, still if you want to use the same feature as of SQL 2000 you can use the column number for ordering(its not recommended in best practice).

select distinct(n_num) from abc_test order by 1

This will order the first column after fetching the result. If you want the ordering should be done based on different column other than distinct then you have to add that column also in select statement and use column number to order by.

select distinct(n_num), k_str from abc_test order by 2
走走停停 2025-01-03 17:08:41

当我遇到同样的错误时,我通过将其更改为来解决它

SELECT n_num 
FROM(
   SELECT DISTINCT(n_num) AS n_num, k_str
   FROM abc_test
) as tbl
ORDER BY tbl.k_str

When I got same error, I got it resolved by changing it as

SELECT n_num 
FROM(
   SELECT DISTINCT(n_num) AS n_num, k_str
   FROM abc_test
) as tbl
ORDER BY tbl.k_str
夜无邪 2025-01-03 17:08:41

我的查询与您的查询不完全匹配,但非常接近。

select distinct a.character_01 , (select top 1 b.sort_order from LookupData b where a.character_01 = b.character_01 )
from LookupData a 
where 
Dataset_Name = 'Sample' and status = 200
order by 2, 1

My query doesn't match yours exactly, but it's pretty close.

select distinct a.character_01 , (select top 1 b.sort_order from LookupData b where a.character_01 = b.character_01 )
from LookupData a 
where 
Dataset_Name = 'Sample' and status = 200
order by 2, 1
半世晨晓 2025-01-03 17:08:41

你试过这个吗?

SELECT DISTINCT n_num as iResult
FROM abc_test 
ORDER BY iResult

did you try this?

SELECT DISTINCT n_num as iResult
FROM abc_test 
ORDER BY iResult
尐偏执 2025-01-03 17:08:41

你可以做

select distinct top 10000 (n_num)  --assuming you won't have more than 10,000 rows                
from abc_test order by(k_str)

you can do

select distinct top 10000 (n_num)  --assuming you won't have more than 10,000 rows                
from abc_test order by(k_str)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文