1,复杂版本(不可取)
我的思路是,假设查询时间段2019-07-01到2019-07-16的所有数据及其和前一天的比率,分别查出2019-07-01到2019-07-16和2019-06-30到2019-07-15的数据,存放于两张临时表,通过date1=date2+1将两张临时表关联起来,这样,当天的 value 值和前天的 value 值就在一条记录里面了,再通过条件比较即可。
临时表:
with t1 as (select aa.*,bb.the_date,bb.val,bb.data_type,bb.this_val,bb.last_val,bb.ctpt from (
select b.SN_METER,a.statistics_date from (
select to_char(to_date('2019-07-01','yyyy-mm-dd')+level-1,'yyyy-mm-dd') as statistics_date from dual
connect by level <=to_date('2019-07-16','yyyy-mm-dd')-to_date('2019-07-01','yyyy-mm-dd')+1
) a
full join V_DT_METER_DAY_ALL_DATA b on 1=1
group by a.statistics_date,b.SN_METER) aa
left join V_DT_METER_DAY_ALL_DATA bb on aa.SN_METER=bb.SN_METER and aa.statistics_date=bb.the_date),
t2 as (select aa.*,bb.the_date,bb.val,bb.data_type,bb.this_val,bb.last_val,bb.ctpt from (
select b.SN_METER,a.statistics_date from (
select to_char(to_date('2019-06-30','yyyy-mm-dd')+level-1,'yyyy-mm-dd') as statistics_date from dual
connect by level <=to_date('2019-07-15','yyyy-mm-dd')-to_date('2019-06-30','yyyy-mm-dd')+1
) a
full join V_DT_METER_DAY_ALL_DATA b on 1=1
group by a.statistics_date,b.SN_METER) aa
left join V_DT_METER_DAY_ALL_DATA bb on aa.SN_METER=bb.SN_METER and aa.statistics_date=bb.the_date)
从临时表里面查询和比较 value :
select t1.sn_meter,t1.statistics_date,t1.val as now_value,t2.val as before_value,
t1.last_val,t1.this_val,t1.data_type,
round((t1.val-t2.val)/t2.val,2) as changeRate
from t1 left join t2
on t1.sn_meter=t2.sn_meter
and to_char(to_date(t1.statistics_date,'yyyy-mm-dd')-1,'yyyy-mm-dd')=t2.statistics_date
where t2.val!=0 and t1.val!=0
union all
select t1.sn_meter,t1.statistics_date,t1.val as now_value,t2.val as before_value,
t1.last_val,t1.this_val,t1.data_type,
9999 as changeRate
from t1 left join t2
on t1.sn_meter=t2.sn_meter
and to_char(to_date(t1.statistics_date,'yyyy-mm-dd')-1,'yyyy-mm-dd')=t2.statistics_date
where t1.val=0
order by sn_meter,statistics_date
如果还有附加条件,可以把这里查到的数据看做一个整体,关联之后再做查询
2,简化版(查找速率提升)
select t1.this_date,t1.this_used,t1.last_used,t1.rate,t2.* from
(select b1.* from
(select a1.meter_guid,a1.this_date,a2.val as this_used,a3.val as last_used,
(case when a3.val=0 then 0 when a2.val=0 then 1 else (a2.val-a3.val)/a3.val end) as rate
from
(select b.meter_guid,a.this_date,a.last_date from
(select to_char(to_date('2019-06-01','yyyy-mm-dd')+level-1,'yyyy-mm-dd') as this_date,
to_char(to_date('2019-06-01','yyyy-mm-dd')+level-2,'yyyy-mm-dd') as last_date from dual
connect by level <=to_date('2019-07-15','yyyy-mm-dd')-to_date('2019-06-01','yyyy-mm-dd')+1) a
inner join table1 b on 1=1 and b.is_load='1' and b.sys_id='01') a1
left join table2 a2 on a1.meter_guid=a2.sn_meter and a1.this_date=a2.the_date
left join table2 a3 on a1.meter_guid=a3.sn_meter and a1.last_date=a3.the_date
)b1 where abs(b1.rate)>=0.2) t1,
(select a.meter_guid,a.customer_no,a.customer_name,a.meter_no,a.cldh,a.meter_model_name,a.wldz,b.cst_name,b.cst_addr
from table3 a,T_RUN_CST b
where a.cst_id=b.cst_id and a.is_load='1' and a.sys_id='01' and a.dot_no like '01%' and a.meter_sort='1'
) t2
where t1.meter_guid=t2.meter_guid
order by t1.meter_guid,t1.this_date;
用 level-1 和 level-2 分别查找当天和前一天的日期,并放在一张表里面,连续关联用量表两次就可以得到分别有当天数据和前一天数据的结果列表,这样就可以直接对两个数据进行比较了,用case then语句代替了 union 除数为0和不为0的两种情况的并集,也是十分的巧妙,select a,b where a.xxx=b.xxx 直接相当于内连接,简化了代码
两种方法的思路是一样的,区别在于后面的方法对sql语句更加熟悉,也不是一次性取出所有数据进行比较,可以提高查询效率