ORDER BY非稳定的排序提一个问题: oracle在order by 排序时,是稳定排序算法吗? 发现用一个type进行排序后,做分页查询,第一页的数据和第二页的数据有重复 怀疑是order by 时,两次排列的顺序不一致

看到业务描述的问题可以得到的结论order by排序不稳定,还有第一个印象就是,type肯定是不唯一的,并且没有索引吧。

这里先科普下排序的稳定性,举个最简单的例子,1,2,3,1,4,5 排序 排序的结果是1,1,2,3,4,5,这时候观察这个1,如果第一个1还是排序前的那个1,那么算法是稳定的。也就是说相等数在排序后不发生交换。

还记得以前数据结构中的几种排序算法:

选择排序复杂度为n*n,不稳定排序,

快速排序复杂度为n*n,不稳定排序,

希尔排序复杂度为nlogn,不稳定排序,

堆排序复杂度为nlogn,不稳定排序,

冒泡排序复杂度为n*n,稳定排序,

插入排序复杂度为n*n,稳定排序,

归并排序复杂度为nlogn,稳定排序

基数排序的复杂度和位数是有关的,是稳定排序。

好了回到正题,本机测试,插入几条测试数据,表结构就两个字段,id和name,没有索引

SELECT ROWNUM,ZZ_TEST.* FROM ZZ_TEST;

1 2 test

2 2 test

3 3 test

4 4 test

5 1 test

可以看到,默认差的时候是是按照rownum排序的。

然后按照name排序,

SELECT ROWNUM,ZZ_TEST.* FROM ZZ_TEST ORDER BY ZZ_TEST."name"

1 2 test

2 2 test

5 1 test

4 4 test

3 3 test

可以看到,排列的顺序不是按照rownum来排序了。

这里再插入一个知识,如何在oracle里查看执行计划,我敲了半天的explain 发现没有用。。。

原来是这么看的,而且消息要比mysql详细多了。:

select * from table(dbms_xplan.display());

-------------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

-------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 8 | 16 (7)| 00:00:01 |

| 1 | SORT ORDER BY | | 1 | 8 | 16 (7)| 00:00:01 |

| 2 | COUNT | | | | | |

| 3 | TABLE ACCESS FULL| ZZ_TEST | 1 | 8 | 15 (0)| 00:00:01 |

-------------------------------------------------------------------------------

好了,那么排序和索引有没有关系呢?

我们先在type上面加一个索引试试,这里我清空了重新插入了5个数据

SELECT ROWNUM,ZZ_TEST.* FROM ZZ_TEST ORDER BY ZZ_TEST."name"

1 3 test

2 4 test

5 2 test

4 1 test

3 5 test

貌似不给力啊老湿。

好,删掉type的索引,在id上加索引,清空表再插入5个数据

SELECT ROWNUM,ZZ_TEST.* FROM ZZ_TEST ORDER BY ZZ_TEST."name"

1 3 test

2 4 test

5 2 test

4 1 test

3 5 test

好吧。原来带上索引都不给力啊。。。

但是不对啊。。。总感觉不对劲啊。没错。。。我TMD一直再用的rownum而不是rowID啊。我一定是最近写分页写多了,坑爹啊。

这里简单的分辨一下rownum和rowid的区别,rownum是返回结果集的一个伪数列,用来标记返回结果的顺序,而rowid是一个物理值用来标记存储位置的。这个值是唯一而固定的

rowid和rownum都是虚列,但含义完全不同。rowid是物理地址,用于定位oracle中具体数据的物理存储位置,而rownum则是sql的输出结果排序。通俗的讲:rowid是相对不变的,rownum会变化,尤其是使用order by的时候。

那么我们再查下rowid试试,这时候表没有索引

SELECT rowid as rono,ROWNUM,ZZ_TEST.* FROM ZZ_TEST ORDER BY ZZ_TEST."name"

AAA7JjAB9AAAD+RAAA 1 3 test

AAA7JjAB9AAAD+RAAB 2 4 test

AAA7JjAB9AAAD+RAAG 5 2 test

AAA7JjAB9AAAD+RAAD 4 1 test

AAA7JjAB9AAAD+RAAC 3 5 test

感觉rowno和rowid一个样子啊

清空表,再在name上建立一个索引,然后在插入5条数据

AAA7JjAB9AAAD+RAAA 1 3 test

AAA7JjAB9AAAD+RAAB 2 4 test

AAA7JjAB9AAAD+RAAG 5 2 test

AAA7JjAB9AAAD+RAAD 4 1 test

AAA7JjAB9AAAD+RAAC 3 5 test

所以,也不是rowid的问题,oralce的排序就是不稳定的。

这里有个小技巧,因为rownum的输出顺序并不是排序的结果 那么如何能输出排序顺序的rownum呢?可以使用嵌套查询,这个和分页写法是一个道理的

select ROWNUM ,t.* from (SELECT rowid rono,ZZ_TEST.* FROM ZZ_TEST ORDER BY ZZ_TEST."name") t

这里再插入一个小知识,如何在oracle下看表的

select * from user_tables

可以查询出所有的用户表

select table_name from user_tables;

查询结果按照in条件顺序输出序输出

业务需要,通过lucene查出符合搜索条件的id,然后在详情表里查出这些id的详情

SELECT id,QUESTION,QUESTIONCOMMENT FROM "ASKDBA_QUESTION" where ID IN (63,62,65,61,64);

其中id是根据搜索的权值进行的排序,sql没有问题,但是通过这种sql查出来的结果的排序就不对了。

61 测试问题101 测试问题101

62 测试问题102 测试问题102

63 测试问题103 测试问题103

64 测试问题104 测试问题104

65 测试问题106 测试问题106

这个一般默认是按照主键来排序的,而并不是根据in中条件的顺序来排列的

网上有个案例是按照in顺序来排序的解决方案,是利用sql server的charindex来解决的。不过仅限于sqlserver

select id,title from info

where id in ('3,1,2,5,4')

order by charindex(','+convert(varchar,ID)+',',',3,1,2,5,4,')

CHARINDEX函数返回字符或者字符串在另一个字符串中的起始位置。CHARINDEX函数调用方法如下:

CHARINDEX ( expression1 , expression2 [ , start_location ] )

Expression1是要到expression2中寻找的字符中,start_location是CHARINDEX函数开始在expression2中找expression1的位置。 CHARINDEX函数返回一个整数,返回的整数是要找的字符串在被找的字符串中的位置。假如CHARINDEX没有找到要找的字符串,那么函数整数“0”

这里有小技巧,可以利用charindex来进行模糊匹配

select name,pass from dps_user where

charindex('张三',dps_user.name)> 0

但是oracle下是怎么实现相同的效果的呢?可以使用decode函数

SELECT id,QUESTION,QUESTIONCOMMENT FROM "ASKDBA_QUESTION" where ID IN (63,62,65,61,64) ORDER BY "DECODE"(id, 63,1,62,2,65,3,61,64);

63 测试问题103 测试问题103

62 测试问题102 测试问题102

65 测试问题106 测试问题106

61 测试问题101 测试问题101

64 测试问题104 测试问题104

结果是符合条件的

oracle和mysql查询条件排序_Oracle数据库中ORDERBY排序和查询按IN条件的顺序输出相关推荐

  1. oracle和mysql文件怎么打开_Oracle vs Mysql--架构、sql查询执行流程及SQL解析顺序区别说明-sql文件怎么打开...

    概述 之前分享的主要是Oracle上的一些内容,那么mysql又有哪些地方不一样呢?下面从MySQL总体架构.sql查询执行流程和语句执行顺序来看一下.. 01 架构总览 下面看一下mysql的架构图 ...

  2. mysql 主键注解_oracle数据库中主键注解

    hibernate5(5)实体映射注解配置[2]主键生成策略 @GeneratedValue基本注解类型 在上一篇文章中,我们讲到了JPA使用@GeneratedValue注解来定义生成策略,而关于注 ...

  3. oracle 排序_Oracle数据库中SQL之过滤和排序数据

    1 过滤 使用WHERE子句,将不满足条件的行过滤掉.WHERE子句紧随FROM子句 SELECT *|{[DISTINCT]column|expression[alias]} FROM table ...

  4. oracle往mysql数据同步存储过程_Oracle数据库之间数据同步

    源库(ENV库)中定义如下包: 包定义如下: CREATE OR REPLACE PACKAGE PKG_DATA_REPORT IS - Author : JOHNFNASH - Created : ...

  5. mysql long raw类型_ORACLE数据库中主要字段类型的读写例子(包括:Long、Raw、Blob)

    这里我用的是ORACLE9I, 建立了表C_EMP1_T,结构如下: create table C_EMP1_T ( EMP_ID         NUMBER(20) not null,    // ...

  6. 数据库中自定义排序规则,Mysql中自定义字段排序规则,Oracle中自定义字段排序规则,decode函数的用法,field函数的用法

    数据库中自定义排序 场景:有一张banner表,表中有一个status字段,有0, 1, 2三个状态位,我想要 1,0,2的自定义排序(这里是重点),然后再进行之上对sequence字段进行二次排序( ...

  7. MySQL数据库中的多表查询含义以及练习~建议码友们点亮拇指+收藏呐~

    MySQL数据库中的多表查询含义以及练习 一. 多表查询含义 二. 多表查询练习 1. 已知表 2. 需求And代码 一. 多表查询含义 查询语法: select列名列表from表名列表where条件 ...

  8. python 更新数据库历史_python 实现数据库中数据添加、查询与更新的示例代码

    一.前言 最近做web网站的测试,遇到很多需要批量造数据的功能:比如某个页面展示数据条数需要达到10000条进行测试,此时手动构造数据肯定是不可能的,此时只能通过python脚本进行自动构造数据:本次 ...

  9. python查询数据库后更新_python 实现数据库中数据添加、查询与更新的示例代码...

    一.前言 最近做web网站的测试,遇到很多需要批量造数据的功能:比如某个页面展示数据条数需要达到10000条进行测试,此时手动构造数据肯定是不可能的,此时只能通过python脚本进行自动构造数据:本次 ...

最新文章

  1. 在JavaScript中删除对象
  2. python安装在哪个盘_python要安装在哪个盘
  3. sizeof和gcvt转换双精度函数的函数不是小结的小结
  4. node JS 微信开发
  5. YAML/Properties配置文件与Spring Boot(转)
  6. [Delphi]ListView基本用法大全
  7. 【知识图谱系列】基于2D卷积的知识图谱嵌入
  8. 带你过一遍:廖雪峰大神Git教程(建议收藏)
  9. 用户心中十大最具影响力国产软件评选揭晓
  10. 剪轴凝截Analdeta.Tessera.Pro.v3.2.2.Build.2015.10.05.Win64 1CD
  11. 航空机票预定系统软件结构图
  12. python量化需要什么基础_真格量化入门课程——②真格量化Python策略编写思路
  13. html表单中按钮居中,Ant design StepsForm中如何使底部按钮居中
  14. 数据分析:OLS回归分析
  15. 国内投资者投资港股的四种方法和港股必知25件事
  16. 查看自己电脑的主板支持多大的内存
  17. python实用案例题
  18. 2021年中国纸包装行业发展现状及市场格局分析[图]
  19. 大治一中2021年高考成绩查询,2021年大冶市高考状元名单资料,今年大冶市高考状元多少分...
  20. 远程服务器 一闪就没有了,远程桌面连接一闪而过的解决方法

热门文章

  1. C++ 网络编程下的socket编程(TCP\UDP),连接下位机
  2. HTTP常见的错误状态码(404、401、500、503等)
  3. EXCEL难题一网打尽 无意间看到的 转过来 自己看看
  4. 苹果M1芯片及新产品布局对ARM生态影响
  5. 论文导读 | 图数据流子图查询
  6. 微信开通检测无需等待准确高的软件
  7. ssm基于微信小程序的游泳馆管理系统 uinapp
  8. 盘点Java技术在生活中的10大应用
  9. 2022年最赚钱地推项目-WiFi贴项目(月入10个W)
  10. 大学生职业生涯发展与规划