我有一个获取两行的查询 -
SELECT tb.type,
tb.value,
tb.comp,
tb.start_date,
tb.end_date,
tb.newdays,
tb.modif_date
FROM table_name tb
WHERE tb.start_date <= sysdate
AND tb.end_date >= sysdate
AND tb.VALUE='ABC'
ORDER BY tb.value,
tb.type DESC
现在这个用来产生这种形式
+------+-------+------+------------+-----------+---------+------------------+
| TYPE | VALUE | COMP | START_DATE | END_DATE | NEWDAYS | MODIF_DATE |
+------+-------+------+------------+-----------+---------+------------------+
| N | ABC | ** | 10-Mar-16 | 31-Dec-99 | 4 | 10/03/2016 10:05 |
| N | ABC | ** | 07-Mar-16 | 31-Dec-99 | 6 | 07/03/2016 23:23 |
+------+-------+------+------------+-----------+---------+------------------+
最近我注意到输出现在是这样的(6个在上面,4个在下面)
+------+-------+------+------------+-----------+---------+------------------+
| TYPE | VALUE | COMP | START_DATE | END_DATE | NEWDAYS | MODIF_DATE |
+------+-------+------+------------+-----------+---------+------------------+
| N | ABC | ** | 07-Mar-16 | 31-Dec-99 | 6 | 07/03/2016 23:23 |
| N | ABC | ** | 10-Mar-16 | 31-Dec-99 | 4 | 10/03/2016 10:05 |
+------+-------+------+------------+-----------+---------+------------------+
如果我删除了ORDER BY CLAUSE tb.type
。结果再次恢复正常(4位于顶部)
混乱 -
1.为什么/如何突然改变?
2.即使tb.type相等,即TYPE='N'
,为什么数据库会对它进行排序/排序?由于两个值都相等,因此不应该进行排序,对吧?
*编辑 - 如果我删除tb.type,则排序再次恢复正常。然而,当我把它放回去时,排序将6放在最顶层。 *
这意味着排序不是任意的。
我的分析 - 通常,当两个值相等时,使用它存储在索引结构中的方式。但是索引的最后一个DDL日期(重建日期)是在2015年。这意味着索引仍然是相同的。
知道为什么会这样吗?
答案 0 :(得分:3)
一般的SQL - 特别是Oracle - 不实现稳定的排序。稳定排序是保留记录原始排序的排序。
SQL表和结果集没有固有的顺序。如果您想要稳定性,order by
中的键需要(组合)是唯一的,无论表格上是否有任何索引。
答案 1 :(得分:1)
文件明确指出 https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_10002.htm
<强> order_by_clause生成强>
使用ORDER BY子句对语句返回的行进行排序。 如果没有order_by_clause,则不保证存在相同的查询 多次执行将以相同的顺序检索行。
- 为什么/它是如何突然改变的?
醇>
因为数据库选择了替代访问路径而不是之前的路径,很可能是由于表增长,统计刷新或者因为创建或删除了某些索引。
请看一下以下简单示例:
create table tetest1 as
select t.*, sysdate - dbms_random.value * 10000 as myDate
from all_objects t;
;
select object_id, object_type
from tetest1
where mydate > sysdate - 2
and object_id between 21000 and 50000
order by object_type;
OBJECT_ID OBJECT_TYPE
---------- -----------------------
47034 JAVA CLASS
31660 JAVA CLASS
47427 SYNONYM
46113 SYNONYM
26042 SYNONYM
21259 SYNONYM
33351 SYNONYM
现在相同的数据,但创建了一个索引:
create index my_idx1 on tetest1( mydate );
select object_id, object_type
from tetest1
where mydate > sysdate - 2
and object_id between 21000 and 50000
order by object_type;
index MY_IDX1 created.
OBJECT_ID OBJECT_TYPE
---------- -----------------------
31660 JAVA CLASS
47034 JAVA CLASS
26042 SYNONYM
33351 SYNONYM
21259 SYNONYM
47427 SYNONYM
46113 SYNONYM
在第一种情况下,数据库使用全表扫描
在第二种情况下,数据库使用索引(不同的访问路径),行顺序不同 - 但在这两种情况下,它都满足查询中所述的要求order by object_type
如果您希望按NEWDAYS列对数据进行排序,请使用:
ORDER BY tb.value,
tb.type DESC,
tb.NEWDAYS