问题描述
嗨
我正在尝试编写一个SQL查询,该查询计算列 (mmwl) 的值,如下所示。
对于DDL和DML脚本,请检查livesql链接
对于y的5个值中的每一个,我需要计算mmwl的值
计算mmwl的公式如下
对于y的第一个值,即y (“28/7/2018 00:01”)
比较 (需要迭代直到y. ie的上界直到5。)
值 _ pvt(1) -值 _ pvt(2) => 1 - 2 = -1
值 _ pvt(2) -值 _ pvt(3) => 2 - 0 = 2
值 _ pvt(3) -值 _ pvt(4) => 0 - 1 = -1
值 _ pvt(4) -值 _ pvt(5) => 1 - 2 = -1
获取差异的最大值
max(-1,2,-1,-1) = 2
所以y('28/7/2018 00:01') 的mmwl值 = 2
-
同样对于y的下一个值
对于y (“28/7/2018 00:02”)
比较
值 _ pvt(1) -值 _ pvt(3) = 1 - 0 = 1
值 _ pvt(2) -值 _ pvt(4) = 2 - 1 = 1
值 _ pvt(3) -值 _ pvt(5) = 0 - 2 = -2
获取差异的最大值
最大 (1,1,-2) = 1
---
这需要持续到倒数第二个记录
最后一条记录即y('28/7/2018 00:05') 的mmwl值将设置为0)
为了获得所需的输出,我创建了一个查询,如下所示
这工作正常,并得到我的输出,但是我很想知道是否有一个更好的方法来做到这一点,使用模型子句或使用模式匹配或递归cte,甚至是一个更好的直sql解决方案。
(注意: t的实际表中会有500多行)
我正在尝试编写一个SQL查询,该查询计算列 (mmwl) 的值,如下所示。
对于DDL和DML脚本,请检查livesql链接
create table t (y date, value_pvt int, mmwl int); --sample data to generate a record insert into t select to_date('28/7/2018','dd/mm/yyyy')+level/24/60 ,mod(level,3) ,null from dual connect by level<=5; select to_char(y,'dd/mm/yyyy hh24:mi:ss') as y ,value_pvt ,mmwl from t order by 1; Y VALUE_PVT MMWL 28/07/2018 00:01:00 1 - 28/07/2018 00:02:00 2 - 28/07/2018 00:03:00 0 - 28/07/2018 00:04:00 1 - 28/07/2018 00:05:00 2 -复制
对于y的5个值中的每一个,我需要计算mmwl的值
计算mmwl的公式如下
对于y的第一个值,即y (“28/7/2018 00:01”)
比较 (需要迭代直到y. ie的上界直到5。)
值 _ pvt(1) -值 _ pvt(2) => 1 - 2 = -1
值 _ pvt(2) -值 _ pvt(3) => 2 - 0 = 2
值 _ pvt(3) -值 _ pvt(4) => 0 - 1 = -1
值 _ pvt(4) -值 _ pvt(5) => 1 - 2 = -1
获取差异的最大值
max(-1,2,-1,-1) = 2
所以y('28/7/2018 00:01') 的mmwl值 = 2
-
同样对于y的下一个值
对于y (“28/7/2018 00:02”)
比较
值 _ pvt(1) -值 _ pvt(3) = 1 - 0 = 1
值 _ pvt(2) -值 _ pvt(4) = 2 - 1 = 1
值 _ pvt(3) -值 _ pvt(5) = 0 - 2 = -2
获取差异的最大值
最大 (1,1,-2) = 1
---
这需要持续到倒数第二个记录
最后一条记录即y('28/7/2018 00:05') 的mmwl值将设置为0)
为了获得所需的输出,我创建了一个查询,如下所示
with data as (select y /* generate a sequence ordered by the y*/ ,value_pvt ,row_number() over(order by y) as rnk ,count(*) over(partition by 1) as tot_cnt from t ) ,row_generator as (select level as lvl /* generate a rows up and till 5*/ from dual connect by level<=(select tot_cnt from data where rownum=1) ) , boundary_values as (select a.lvl /* generate records for levels and specify the max and min values of the boundaries. Eg:for lvl=4 low_val=1 and hi_val=5*/ ,b.lvl as low_val ,a.lvl+b.lvl as hi_val from row_generator a join row_generator b on 1=1 where b.lvl + a.lvl <=(select tot_cnt from data where rownum=1) ) , computed_mmwl as ( select lvl,max(diff) as diff from (select m.lvl ,n.value_pvt - o.value_pvt as diff from boundary_values m join data n on m.low_val=n.rnk join data o on m.hi_val=o.rnk ) group by lvl union all select max(rnk), 0 /* this union all adds the last record ie y('28/07/2018 00:05:00')|0 */ from data ) select to_char(a1.y,'dd/mm/yyyy hh24:mi:ss') as y ,a1.value_pvt ,b1.diff as new_mmwl from data a1 join computed_mmwl b1 on a1.rnk=b1.lvl复制
这工作正常,并得到我的输出,但是我很想知道是否有一个更好的方法来做到这一点,使用模型子句或使用模式匹配或递归cte,甚至是一个更好的直sql解决方案。
(注意: t的实际表中会有500多行)
专家解答
所以,对于位置N (按y排序) 的每一行,你是:
-查找每一行的当前val和之后的val N行之间的差异
-返回这些差异中最大的?
如果是这样,我相信您必须将表与另一个具有相同行数的表交叉连接。
但是有一种比递归更简单的方法来获得差异。
lead的第二个参数陈述了当前之后的多少行,以获得的值。所以使用这个,由N分区,生成所有的差异组合。
然后使用nth_value函数获取此N的Y和PVT值。
最后按nth_value输出分组,找出最大差值。这给出了:
-查找每一行的当前val和之后的val N行之间的差异
-返回这些差异中最大的?
如果是这样,我相信您必须将表与另一个具有相同行数的表交叉连接。
但是有一种比递归更简单的方法来获得差异。
lead的第二个参数陈述了当前之后的多少行,以获得的值。所以使用这个,由N分区,生成所有的差异组合。
然后使用nth_value函数获取此N的Y和PVT值。
最后按nth_value输出分组,找出最大差值。这给出了:
with ranks as ( select t.*, row_number () over ( order by y ) rn, count (*) over () c from t ), grps as ( select value_pvt - lead ( value_pvt, x ) over ( partition by x order by rn ) diff, nth_value ( y, x ) over ( partition by x ) nth_y, nth_value ( value_pvt, x ) over ( partition by x ) nth_pvt from ranks r , lateral ( select level x from dual connect by level <= c ) rws ) select nth_y, nth_pvt, nvl ( max ( diff ), 0 ) from grps group by nth_y, nth_pvt order by nth_y; NTH_Y NTH_PVT NVL(MAX(DIFF),0) 28-JUL-2018 00:01:00 1 2 28-JUL-2018 00:02:00 2 1 28-JUL-2018 00:03:00 0 0 28-JUL-2018 00:04:00 1 -1 28-JUL-2018 00:05:00 2 0复制
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
Oracle DataGuard高可用性解决方案详解
孙莹
504次阅读
2025-03-26 23:27:33
Oracle RAC 一键安装翻车?手把手教你如何排错!
Lucifer三思而后行
483次阅读
2025-04-15 17:24:06
墨天轮个人数说知识点合集
JiekeXu
405次阅读
2025-04-01 15:56:03
XTTS跨版本迁移升级方案(11g to 19c RAC for Linux)
zwtian
398次阅读
2025-04-08 09:12:48
Oracle SQL 执行计划分析与优化指南
Digital Observer
374次阅读
2025-04-01 11:08:44
【纯干货】Oracle 19C RU 19.27 发布,如何快速升级和安装?
Lucifer三思而后行
360次阅读
2025-04-18 14:18:38
Oracle 19c RAC更换IP实战,运维必看!
szrsu
343次阅读
2025-04-08 23:57:08
oracle定时任务常用攻略
virvle
316次阅读
2025-03-25 16:05:19
3月“墨力原创作者计划”获奖名单公布
墨天轮编辑部
315次阅读
2025-04-15 14:48:05
风口浪尖!诚通证券扩容采购Oracle 793万...
Roger的数据库专栏
311次阅读
2025-03-24 09:42:53