Oracle 按子查询排序和ROWNUM违背了关系哲学?
ORDER BY之前应用Oracle的ROWNUM。为了根据已排序的列放置ROWNUM,在所有文档和文本中都提出了以下子查询Oracle 按子查询排序和ROWNUM违背了关系哲学?,oracle,oracle11g,relational-database,sql-order-by,rownum,Oracle,Oracle11g,Relational Database,Sql Order By,Rownum,ORDER BY之前应用Oracle的ROWNUM。为了根据已排序的列放置ROWNUM,在所有文档和文本中都提出了以下子查询 select * from ( select * from table order by price ) where rownum <= 7 那让我讨厌。据我所知,FROM中的表输入是关系型的,因此不存储顺序,这意味着FROM看到子查询中的顺序时不受尊重 我记不起确切的场景,但ORDER BY这一事实在我读过不止一次的外部查询中没有影响。例如,内联子查
select *
from (
select *
from table
order by price
)
where rownum <= 7
那让我讨厌。据我所知,FROM中的表输入是关系型的,因此不存储顺序,这意味着FROM看到子查询中的顺序时不受尊重
我记不起确切的场景,但ORDER BY这一事实在我读过不止一次的外部查询中没有影响。例如,内联子查询、INSERT子查询、PARTITION子句的ORDER BY等
按姓名按工资顺序划分
在外部查询中,薪资顺序将不受尊重,如果我们希望在外部查询输出时对薪资进行排序,则需要在外部查询中添加另一个排序依据
每个人都对为什么不尊重关系属性以及为什么顺序存储在子查询中有一些见解?在这种情况下,order BY实际上是Oracle的专有语法,用于在逻辑上无序的行集合上生成有序的行号。在我看来,这是一个设计拙劣的功能,但在Oracle中同样有效的等效ISO标准SQL ROW_NUMBER函数可能会更清楚地说明发生了什么:
select *
from (
select ROW_NUMBER() OVER (ORDER BY price) rn, *
from table
) t
where rn <= 7;
在本例中,ORDER BY在逻辑上属于哪个位置:作为派生行编号属性规范的一部分。这比Oracle版本更强大,因为您可以在同一结果中指定多个定义不同行号的不同排序。此查询返回的行的实际顺序未定义。我相信在您的Oracle特定版本的查询中也是如此,因为当您以这种方式使用ORDER BY时,无法保证订购
值得记住的是,Oracle不是关系型DBMS。与其他SQL DBMS一样,Oracle在某些基本方面偏离了关系模型。产品中存在隐式排序和DISTINCT等功能,这正是因为SQL数据模型的非关系性质,因此需要处理具有重复行的无键表。在这种情况下,ORDER BY实际上是Oracle用于在逻辑上生成有序行号的专有语法无序的行集合。在我看来,这是一个设计拙劣的功能,但在Oracle中同样有效的等效ISO标准SQL ROW_NUMBER函数可能会更清楚地说明发生了什么:
select *
from (
select ROW_NUMBER() OVER (ORDER BY price) rn, *
from table
) t
where rn <= 7;
在本例中,ORDER BY在逻辑上属于哪个位置:作为派生行编号属性规范的一部分。这比Oracle版本更强大,因为您可以在同一结果中指定多个定义不同行号的不同排序。此查询返回的行的实际顺序未定义。我相信在您的Oracle特定版本的查询中也是如此,因为当您以这种方式使用ORDER BY时,无法保证订购
值得记住的是,Oracle不是关系型DBMS。与其他SQL DBMS一样,Oracle在某些基本方面偏离了关系模型。产品中存在隐式排序和DISTINCT等功能,这正是因为SQL数据模型的非关系性质以及随后需要处理具有重复行的无键表。毫不奇怪,Oracle将此视为一种特殊情况。你可以从执行计划中看到这一点。由于有时会出现不正确/不确定的限制版本,您将获得排序顺序和计数停止键操作:
select *
from my_table
where rownum <= 7
order by price;
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 3 (34)| 00:00:01 |
| 1 | SORT ORDER BY | | 1 | 13 | 3 (34)| 00:00:01 |
|* 2 | COUNT STOPKEY | | | | | |
| 3 | TABLE ACCESS FULL| MY_TABLE | 1 | 13 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(ROWNUM<=7)
使用通常的子查询/ROWNUM构造,您会得到一些不同的结果
select *
from (
select *
from my_table
order by price
)
where rownum <= 7;
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 3 (34)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | VIEW | | 1 | 13 | 3 (34)| 00:00:01 |
|* 3 | SORT ORDER BY STOPKEY| | 1 | 13 | 3 (34)| 00:00:01 |
| 4 | TABLE ACCESS FULL | MY_TABLE | 1 | 13 | 2 (0)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<=7)
3 - filter(ROWNUM<=7)
毫不奇怪,甲骨文将此视为一种特殊情况。你可以从执行计划中看到这一点。由于有时会出现不正确/不确定的限制版本,您将获得排序顺序和计数停止键操作:
select *
from my_table
where rownum <= 7
order by price;
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 3 (34)| 00:00:01 |
| 1 | SORT ORDER BY | | 1 | 13 | 3 (34)| 00:00:01 |
|* 2 | COUNT STOPKEY | | | | | |
| 3 | TABLE ACCESS FULL| MY_TABLE | 1 | 13 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(ROWNUM<=7)
使用通常的子查询/ROWNUM构造,您会得到一些不同的结果
select *
from (
select *
from my_table
order by price
)
where rownum <= 7;
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 3 (34)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | VIEW | | 1 | 13 | 3 (34)| 00:00:01 |
|* 3 | SORT ORDER BY STOPKEY| | 1 | 13 | 3 (34)| 00:00:01 |
| 4 | TABLE ACCESS FULL | MY_TABLE | 1 | 13 | 2 (0)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<=7)
3 - filter(ROWNUM<=7)
除了sqlvogel的好答案之外: 据我所知,FROM中的表输入是关系型的 否,从中输入的表不是关系型的。它不是关系型的,因为表输入是表,而表不是关系型的。SQL中的无数怪癖和奇怪之处最终都归结为一个简单的事实:SQL中的核心构建块是表,而表不是关系。总结这些差异: 表可以包含重复的行,关系不能包含重复的行。因此,SQL提供了包代数,而不是关系代数。另一个结果是,SQL甚至不可能为其最基本的构建块定义相等比较!!!考虑到可能需要处理重复的行,如何比较表的相等性 表可以包含未命名的列,关系不能包含。从…中选择X+Y。。。因此,SQL被按顺序位置强制进入列标识,并作为
因为关系表和查询结果从不包含重复的行,所以在关系模型下不存在重复。SQLDBMS-RDBMS。在关系代数中,SELECT语句相当于一个投影:πhire_dateemployees。投影总是返回不同的元组,在这种情况下是不同的租用日期。不,这并不意味着RM坏了。谢谢Alex的输入。我脑海中闪过这样一个想法:是否内部查询SELECT*实际上在实际表列旁边包含伪列ROWNUM和ROWID,并且这些伪列被传递到外部查询,因此保持顺序?或者ROWNUM仅在引用时才起作用?@Kenny-内部查询有自己的ROWNUM psuedocolumn,但正如您所注意到的,它是在应用order by之前生成的。您可以查看它,甚至给它一个别名,以便外部查询可以看到它。但它在逻辑上不一定与外部查询中的ROWNUM具有相同的值。例如,尝试:选择t.*,从选择我的表中选择rownum.*,从我的表中选择rownum作为rn,按价格t排序,其中rownum感谢您的输入。我脑海中闪过这样一个想法:是否内部查询SELECT*实际上在实际表列旁边包含伪列ROWNUM和ROWID,并且这些伪列被传递到外部查询,因此保持顺序?或者ROWNUM仅在引用时才起作用?@Kenny-内部查询有自己的ROWNUM psuedocolumn,但正如您所注意到的,它是在应用order by之前生成的。您可以查看它,甚至给它一个别名,以便外部查询可以看到它。但它在逻辑上不一定与外部查询中的ROWNUM具有相同的值。例如,请尝试:选择t.*,从选择我的表中选择rownum.*,从我的表中选择rownum作为rn按价格排序,其中rownum rownum和order by都不是关系概念。rownum和order by都不是关系概念。