ORACLE SQL:查找上一个最小和最大连续周期
我有下面的样本数据集,其中列出了在特定范围内(2016年1月至2018年12月)因特定原因无法工作的水表 我想有一个查询,检索最后一个最大和最小连续周期,其中仪表不在该周期范围内工作ORACLE SQL:查找上一个最小和最大连续周期,sql,oracle,Sql,Oracle,我有下面的样本数据集,其中列出了在特定范围内(2016年1月至2018年12月)因特定原因无法工作的水表 我想有一个查询,检索最后一个最大和最小连续周期,其中仪表不在该周期范围内工作 任何帮助都将不胜感激。使用group by的聚合功能 select max(mdrg_per_period) mdrg_per_period, mrdg_acc_code,max(mrdg_date_read),rea_Desc,min(mdrg_per_period) not_working_as_from
任何帮助都将不胜感激。使用group by的聚合功能
select max(mdrg_per_period) mdrg_per_period, mrdg_acc_code,max(mrdg_date_read),rea_Desc,min(mdrg_per_period) not_working_as_from
from tablename
group by mrdg_acc_code,rea_Desc
这有点棘手。这是一个缺口和岛屿问题。要获得所有连续期间,如果您有一个月的枚举,这将很有帮助。因此,将周期转换为月数,然后减去使用
行数()生成的序列。在相邻的几个月内,差异是恒定的
这看起来像:
select acc_code, min(period), max(period)
from (select t.*,
row_number() over (partition by acc_code order by period_num) as seqnum
from (select t.*, floor(period / 100) * 12 + mod(period, 100) as period_num
from t
) t
where rea_desc = 'METER NOT WORKING'
) t
group by (period_num - seqnum);
然后,如果您想要每个帐户的最后一个,可以使用子查询:
select t.*
from (select acc_code, min(period), max(period),
row_number() over (partition by acc_code order by max(period desc) as seqnum
from (select t.*,
row_number() over (partition by acc_code order by period_num) as seqnum
from (select t.*, floor(period / 100) * 12 + mod(period, 100) as period_num
from t
) t
where rea_desc = 'METER NOT WORKING'
) t
group by (period_num - seqnum)
) t
where seqnum = 1;
您有两个选择:
select code, to_char(min_period, 'yyyymm') min_period, to_char(max_period, 'yyyymm') max_period
from (
select code, min(period) min_period, max(period) max_period,
max(min(period)) over (partition by code) max_min_period
from (
select code, period, sum(flag) over (partition by code order by period) grp
from (
select code, period,
case when add_months(period, -1)
= lag(period) over (partition by code order by period)
then 0 else 1 end flag
from (select mrdg_acc_code code, to_date(mrdg_per_period, 'yyyymm') period from t)))
group by code, grp)
where min_period = max_min_period
说明:
- 标记期间不等于上一期间加上一个月的行
- 创建列
grp
,该列对标志进行连续求和
- 使用
code
和grp
对数据进行分组,并额外查找最大期初
- 仅显示
min\u period
=max\u-min\u period
第二个选项是Oracle 11g及更高版本中提供的递归CTE:
with
data(period, code) as (
select to_date(mrdg_per_period, 'yyyymm'), mrdg_acc_code from t
where mrdg_per_period between 201601 and 201812),
cte (period, code) as (
select to_char(period, 'yyyymm'), code from data
where (period, code) in (select max(period), code from data group by code)
union all
select to_char(data.period, 'yyyymm'), cte.code
from cte
join data on data.code = cte.code
and data.period = add_months(to_date(cte.period, 'yyyymm'), -1))
select code, min(period) min_period, max(period) max_period
from cte group by code
说明:
- 子查询
数据
仅过滤2016
-2018
中的行,另外将期间转换为日期格式。我们需要这个函数来增加月数
cte
是递归的。锚点查找起始行,这些行具有每个代码的最大周期。union all
之后是递归成员,它查找比当前行早一个月的行。如果它找到它,则为净行,如果没有,则停止
cte
拒绝了不连续的时段下面是两个查询的示例。祝你好运。hi fa06,我也试过了,但没有达到预期的效果。例如,对于账户0101000010,我每次得到的最短周期是201601,但最后一个最短周期应该是201610谢谢你仔细思考Stibbons:)的解释。它起作用了。我是dba新手,有许多类似的报告要处理。我现在已经理解了这一概念,其他报告也是如此。多谢各位。