我有以下示例数据集,其中列出了在特定范围内(2016年1月至2018年12月)由于特定原因无法使用的水表。
我想查询一个查询,该查询检索在该时间段内仪表不工作的最近的最大和最小连续时间段。
任何帮助将不胜感激。
答案 0 :(得分:1)
将聚合函数与分组依据一起使用
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
答案 1 :(得分: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_period
= max_min_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
说明:
data
仅过滤2016
-2018
另外将期间转换为日期格式的行。我们需要此功能才能使功能add_months
正常工作。cte
是递归的。锚查找起始行,这些起始行的每个代码的周期最长。在union all
是递归成员之后,它比当前日期早一个月 查找行。如果找到它,则排净,如果没有,则停止。cte
拒绝了不连续的时间段。尽管递归查询比传统查询要慢,但在某些情况下,第二种解决方案更好。
这是两个查询的dbfiddle demo。祝你好运。
答案 2 :(得分:0)
这有点棘手。这是一个空白问题。要获得所有连续的时间段,如果您有一个月的枚举,这将有所帮助。因此,将周期转换为月数,然后减去使用row_number()
生成的序列。一组相邻月份的差异是恒定的。
这看起来像:
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;