新三种求数列中值SQL之效率再比拼
在 https://www.cnblogs.com/xiandedanteng/p/12677688.html 中我列举了三种求中值方案,其中日本人MICK的做法因为不适用于二百万结果集而放弃,取而代之是新方案一。
新方案一:
经过思考后我又得出了一种中值的新解法,那就是利用排序后正向序列和反向序列交叉点为中值区的原理,如果两个序列相减小于等于一则求所在区域的均值即可。
SQL:
- select avg(a.salary) from
- (select salary,dense_rank() over (order by salary asc) as seq,dense_rank() over (order by salary desc) as revseq from tb_employee order by salary) a where abs(a.seq-a.revseq)<=1
解释计划:
- SQL> select avg(a.salary) from
- 2 (select salary,dense_rank() over (order by salary asc) as seq,dense_rank() over (order by salary desc) as revseq from tb_employee order by salary) a where abs(a.seq-a.revseq)<=1;
- 已用时间: 00: 00: 00.00
- 执行计划
- ----------------------------------------------------------
- Plan hash value: 9035349
- ---------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
- ---------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | 39 | | 8850 (2)| 00:01:47 |
- | 1 | SORT AGGREGATE | | 1 | 39 | | | |
- |* 2 | VIEW | | 2000K| 74M| | 8850 (2)| 00:01:47 |
- | 3 | WINDOW SORT | | 2000K| 7812K| 22M| 8850 (2)| 00:01:47 |
- | 4 | WINDOW SORT | | 2000K| 7812K| 22M| 8850 (2)| 00:01:47 |
- | 5 | TABLE ACCESS FULL| TB_EMPLOYEE | 2000K| 7812K| | 3045 (2)| 00:00:37 |
- ---------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 2 - filter(ABS("A"."SEQ"-"A"."REVSEQ")<=1)
从Cost看是目前最快的。
执行时间:
- SQL> select avg(a.salary) from
- 2 (select salary,dense_rank() over (order by salary asc) as seq,dense_rank() over (order by salary desc) as revseq from tb_employee order by salary) a where abs(a.seq-a.revseq)<=1;
- AVG(A.SALARY)
- -------------
- 5500
- 已用时间: 00: 00: 02.46
从运行时间上看排第二。
经局部优化后两种方案SQL如下:
原有方案二:
- select avg(b.salary) from
- (select a.salary,abs(a.seq-a.revseq) as diff from (select id,salary,dense_rank() over (order by salary asc) as seq,dense_rank() over (order by salary desc) as revseq from tb_employee order by salary) a ) b
- where b.diff=(select min(c.diff) from
- (select abs(a.seq-a.revseq) as diff from (select dense_rank() over (order by salary asc) as seq,dense_rank() over (order by salary desc) as revseq from tb_employee order by salary) a ) c)
解释计划:
- SQL> select avg(b.salary) from
- 2 (select a.salary,abs(a.seq-a.revseq) as diff from (select id,salary,dense_rank() over (order by salary asc) as seq,dense_rank() over (order by salary desc) as revseq from tb_employee order by salary) a ) b
- 3 where b.diff=(select min(c.diff) from
- 4 (select abs(a.seq-a.revseq) as diff from (select dense_rank() over (order by salary asc) as seq,dense_rank() over (order by salary desc) as revseq from tb_employee order by salary) a ) c);
- 已用时间: 00: 00: 00.00
- 执行计划
- ----------------------------------------------------------
- Plan hash value: 3874635296
- -----------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
- -----------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | 39 | | 19969 (2)| 00:04:00 |
- | 1 | SORT AGGREGATE | | 1 | 39 | | | |
- |* 2 | VIEW | | 2000K| 74M| | 11119 (2)| 00:02:14 |
- | 3 | WINDOW SORT | | 2000K| 19M| 38M| 11119 (2)| 00:02:14 |
- | 4 | WINDOW SORT | | 2000K| 19M| 38M| 11119 (2)| 00:02:14 |
- | 5 | TABLE ACCESS FULL | TB_EMPLOYEE | 2000K| 19M| | 3045 (2)| 00:00:37 |
- | 6 | SORT AGGREGATE | | 1 | 26 | | | |
- | 7 | VIEW | | 2000K| 49M| | 8850 (2)| 00:01:47 |
- | 8 | WINDOW SORT | | 2000K| 7812K| 22M| 8850 (2)| 00:01:47 |
- | 9 | WINDOW SORT | | 2000K| 7812K| 22M| 8850 (2)| 00:01:47 |
- | 10 | TABLE ACCESS FULL| TB_EMPLOYEE | 2000K| 7812K| | 3045 (2)| 00:00:37 |
- -----------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 2 - filter(ABS("A"."SEQ"-"A"."REVSEQ")= (SELECT MIN(ABS("A"."SEQ"-"A"."REVSEQ"))
- FROM (SELECT DENSE_RANK() OVER ( ORDER BY "SALARY") "SEQ",DENSE_RANK() OVER ( ORDER
- BY INTERNAL_FUNCTION("SALARY") DESC ) "REVSEQ" FROM "TB_EMPLOYEE" "TB_EMPLOYEE" ORDER
- BY "SALARY") "A"))
执行时间:
SQL> select avg(b.salary) from
2 (select a.salary,abs(a.seq-a.revseq) as diff from (select id,salary,dense_rank() over (order by salary asc) as seq,dense_rank() over (order by salary desc) as revseq from tb_employee order by salary) a ) b
3 where b.diff=(select min(c.diff) from
4 (select abs(a.seq-a.revseq) as diff from (select dense_rank() over (order by salary asc) as seq,dense_rank() over (order by salary desc) as revseq from tb_employee order by salary) a ) c);
AVG(B.SALARY)
-------------
5500
已用时间: 00: 00: 04.56
原有方案三:
- select avg(a.salary) from
- (select
- salary,row_number() over (order by salary asc) as seq,row_number() over (order by salary desc) as revseq,(select ceil(count(*)/2) from tb_employee) as ceil
- from tb_employee) a
- where a.seq=a.ceil or a.revseq=a.ceil
解释计划:
- SQL> select avg(a.salary) from
- 2 (select
- 3 salary,row_number() over (order by salary asc) as seq,row_number() over (order by salary desc) as revseq,(select ceil(count(*)/2) from tb_employee) as ceil
- 4 from tb_employee) a
- 5 where a.seq=a.ceil or a.revseq=a.ceil;
- 已用时间: 00: 00: 00.00
- 执行计划
- ----------------------------------------------------------
- Plan hash value: 3541675306
- -----------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
- -----------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | 52 | | 14656 (3)| 00:02:56 |
- | 1 | SORT AGGREGATE | | 1 | 52 | | | |
- | 2 | SORT AGGREGATE | | 1 | | | | |
- | 3 | INDEX FAST FULL SCAN| SYS_C0012264 | 2000K| | | 1474 (2)| 00:00:18 |
- |* 4 | VIEW | | 2000K| 99M| | 14656 (3)| 00:02:56 |
- | 5 | WINDOW SORT | | 2000K| 7812K| 22M| 14656 (3)| 00:02:56 |
- | 6 | WINDOW SORT | | 2000K| 7812K| 22M| 14656 (3)| 00:02:56 |
- | 7 | TABLE ACCESS FULL | TB_EMPLOYEE | 2000K| 7812K| | 3045 (2)| 00:00:37 |
- -----------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 4 - filter("A"."SEQ"="A"."CEIL" OR "A"."REVSEQ"="A"."CEIL")
消耗时间:
- SQL> ;
- 1 select avg(b.salary) from
- 2 (select
- 3 salary,row_number() over (order by salary asc) as seq,row_number() over (order by salary desc) as revseq,(select ceil(count(*)/2) from tb_employee) as ceil
- 4 - filter("A"."SEQ"="A"."CEIL" OR "A"."REVSEQ"="A"."CEIL");
- 5* where a.seq=a.ceil or a.revseq=a.ceil
- SQL> select avg(a.salary) from
- 2 (select
- 3 salary,row_number() over (order by salary asc) as seq,row_number() over (order by salary desc) as revseq,(select ceil(count(*)/2) from tb_employee) as ceil
- 4 from tb_employee) a
- 5 where a.seq=a.ceil or a.revseq=a.ceil;
- AVG(A.SALARY)
- -------------
- 5498
- 已用时间: 00: 00: 01.98
而单查表数量的解释计划大家也参考看一下:
- SQL> select count(*) from tb_employee;
- 已用时间: 00: 00: 00.01
- 执行计划
- ----------------------------------------------------------
- Plan hash value: 2866911338
- ------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Cost (%CPU)| Time |
- ------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | 1474 (2)| 00:00:18 |
- | 1 | SORT AGGREGATE | | 1 | | |
- | 2 | INDEX FAST FULL SCAN| SYS_C0012264 | 2000K| 1474 (2)| 00:00:18 |
- ------------------------------------------------------------------------------
最后的大比拼表格:
方案 | Cost | 耗时 |
新方案一 | 8850 | 2.46秒 |
原有方案二 | 19946 | 4.56秒 |
原有方案三 | 14646 | 1.98 |
截至目前,方案三以较高效率胜出,新方案一其实也不错,原有方案三排第三位。
--2020年4月12日--
新三种求数列中值SQL之效率再比拼的更多相关文章
- Python max()方法扩展:求字典中值最大的键
重要的应该写在前面[捂脸] 场景一:仅求最大值对应的键,代码如下: >>> dic = {'A':4, 'B':2, 'C':3} >>> max_key = ...
- C#中??和?分别是什么意思? 在ASP.NET开发中一些单词的标准缩写 C#SESSION丢失问题的解决办法 在C#中INTERFACE与ABSTRACT CLASS的区别 SQL命令语句小技巧 JQUERY判断CHECKBOX是否选中三种方法 JS中!=、==、!==、===的用法和区别 在对象比较中,对象相等和对象一致分别指的是什么?
C#中??和?分别是什么意思? 在C#中??和?分别是什么意思? 1. 可空类型修饰符(?):引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空.例如:string str=null; ...
- 【算法随记三】小半径中值模糊的急速实现(16MB图7.5ms实现) + Photoshop中蒙尘和划痕算法解读。
在本人的博客里,分享了有关中值模糊的O(1)算法,详见:任意半径中值滤波(扩展至百分比滤波器)O(1)时间复杂度算法的原理.实现及效果 ,这里的算法的执行时间和参数是无关的.整体来说,虽然速度也很快, ...
- java数组中的三种排序方法中的冒泡排序方法
我记得我大学学java的时候,怎么就是搞不明白这三种排序方法,也一直不会,现在我有发过来学习下这三种方法并记录下来. 首先说说冒泡排序方法:冒泡排序方法就是把数组中的每一个元素进行比较,如果第i个元素 ...
- Python 列表(List) 的三种遍历(序号和值)方法
三种遍历列表里面序号和值的方法: 最近学习python这门语言,感觉到其对自己的工作效率有很大的提升,特在情人节这一天写下了这篇博客,下面废话不多说,直接贴代码 #!/usr/bin/env pyth ...
- [ 原创 ]学习笔记-三种向ListView中填充简单文本的方法
Android 中ListView是很重要的一块内容 掌握ListView的基本用法 对学习安卓起着举足轻重的作用 今天就介绍一下三种向ListView 填充简单文本的方法 填充其他数据类型的用法之后 ...
- 求数列中第K大的数
原创 利用到快速排序的思想,快速排序思想:https://www.cnblogs.com/chiweiming/p/9188984.html array代表存放数列的数组,K代表第K大的数,mid代表 ...
- C#三种判断数据库中取出的字段值是否为空(NULL) 的方法
操作数据库,需要判断返回的字段值是否为空,收集了3种方法供参考 1 通过System.DBNull判断,网上大部分都使用这个方法. DataTable dt; ...
- Spring之jdbcTemplate:查询的三种方式(单个值、单个对象、对象集合)
JdbcTemplateDemo2.java package helloworld.jdbcTemplate; import org.springframework.jdbc.core.JdbcTem ...
随机推荐
- 学习Hibernate5这一篇就够了
配套资料,免费下载 链接:https://pan.baidu.com/s/1i_RXtOyN1e4MMph6V7ZF-g 提取码:8dw6 复制这段内容后打开百度网盘手机App,操作更方便哦 第一章 ...
- C++运用栈实现网络浏览器的“前进”与“后退”功能
在用户最近访问的网页中进行“前进”和“后退”是Web浏览器的常用功能,实现该功能的一种方式是使用两个栈(backward 栈和forward栈)来存储用户访问的网址,用户的不同操作对应的具体实现方法如 ...
- LeetCode198 House Robber(打家劫舍)
题目 You are a professional robber planning to rob houses along a street. Each house has a certain amo ...
- myBatis源码解析-反射篇(4)
前沿 前文分析了mybatis的日志包,缓存包,数据源包.源码实在有点难顶,在分析反射包时,花费了较多时间.废话不多说,开始源码之路. 反射包feflection在mybatis路径如下: 源码解析 ...
- kereas 实现鸢尾花分类
import tensorflow as tf from sklearn import datasets import numpy as np x_train=datasets.load_iris() ...
- day5 字符串 函数
字符串 1.单引号,双引号,三引号括起来的都是字符串 索引 从0开始 str[0] 遍历 for循环 判断字符串中是否都是数字 ,字母 返回bool型 ...
- 不安装证书如何通过模拟器+Fiddler抓包APP的HTTPS请求?
模拟器抓取https方法 说明:为了解决安卓手线上不能抓取https请求,以下整理通过模拟器抓取https请求方法如下:前置条件:安卓模拟器:夜神抓包工具:Fiddler汉化中文升级版1无需FIDDL ...
- 在我们使用Redis作为一个LRU缓存的时候,怎么做才能更高效
当用Redis作为一个LRU存储时,有些时候是比较方便的,在你增添新的数据时会自动驱逐旧的数据.这种行为在开发者论坛是非常有名的,因为这是流行的memcached系统的默认行为. LRU实际上只是支持 ...
- DHCPV6 vs DHCPV4
原文链接:https://blog.csdn.net/kdb_viewer/article/details/83310904 一.DHCPv4 vs DHCPv6 1. 相同点 使用DHCP clie ...
- Solon详解(五)- Solon扩展机制之Solon Plugin
Solon 中也有一种非常解耦的扩展机制:Solon Plugin.这种扩展机制和Spring Factories很像,和SPI也很像. 一.Solon 中的扩展机制 在Solon的扩展插件加载机制, ...