Sql 将单个日期值转换为日期间隔
我需要一个查询,将不一定连续的单个日期行添加到考虑对象id的间隔中 我有一个select查询,它返回以下数据Sql 将单个日期值转换为日期间隔,sql,oracle,gaps-and-islands,Sql,Oracle,Gaps And Islands,我需要一个查询,将不一定连续的单个日期行添加到考虑对象id的间隔中 我有一个select查询,它返回以下数据 id date 9465 12/12/20 9465 12/12/21 9465 12/12/22 9465 12/12/25 9465 12/12/26 9466 12/12/21 9466 12/12/22 9466 12/12/23 9466 12/12/24 9466 12/12/25 9466 12
id date
9465 12/12/20
9465 12/12/21
9465 12/12/22
9465 12/12/25
9465 12/12/26
9466 12/12/21
9466 12/12/22
9466 12/12/23
9466 12/12/24
9466 12/12/25
9466 12/12/27
我需要一个查询,使用上面的子查询将输出如下数据:
id date_from date_till
9465 12/12/20 12/12/22
9465 12/12/25 12/12/26
9466 12/12/21 12/12/25
9466 12/12/27 12/12/27
我们可以通过几个分析来实现这一点:
SQL> alter session set nls_date_format='yy/mm/dd';
Session altered.
SQL> select id, min(val) date_from, max(val) date_till
2 from (select id, val, max(grp) over(partition by id order by val) grp
3 from (select id, val, lag(val, 1) over(partition by id order by val),
4 case
5 when lag(val, 1) over(partition by id order by val) < val - 1 then
6 row_number() over(partition by id order by val)
7 when row_number() over(partition by id order by val) = 1 then
8 1
9 end grp
10 from mytab))
11 group by id, grp
12 order by id, date_from
13 /
ID DATE_FRO DATE_TIL
---------- -------- --------
9465 12/12/20 12/12/22
9465 12/12/25 12/12/26
9466 12/12/21 12/12/25
9466 12/12/27 12/12/27
接下来我们需要填充空格,以便空格关联前面的非空组。i、 e.我们将max应用于此,其中maxgrp overpartition by id order by val此处的order表示我们仅获取到该点的max行,而不是整个集合的max行
SQL> select id, val, max(grp) over(partition by id order by val) grp
2 from (select id, val, lag(val, 1) over(partition by id order by val),
3 case
4 when lag(val, 1) over(partition by id order by val) < val - 1 then
5 row_number() over(partition by id order by val)
6 when row_number() over(partition by id order by val) = 1 then
7 1
8 end grp
9 from mytab)
10 /
ID VAL GRP
---------- -------- ----------
9465 12/12/20 1
9465 12/12/21 1
9465 12/12/22 1
9465 12/12/25 4
9465 12/12/26 4
9466 12/12/21 1
9466 12/12/22 1
9466 12/12/23 1
9466 12/12/24 1
9466 12/12/25 1
9466 12/12/27 6
11 rows selected.
现在它是一个简单的按id分组的应用程序,即grp,取每个id+组的最小值和最大值。这就是所谓的孤岛问题。以下是基于Oracle的解决方案的方法:
我喜欢用一个小技巧来解决这个问题,使用分析函数。如果我们枚举每一行,然后从日期中减去该值,则顺序中的日期是常量。这是组id。然后是一个简单的聚合问题:
select id, min(date) as date_from, max(date) as date_to
from (select (date - row_number() over (partition by id order by date)) as groupid,
t.*
from t
)
group by id, groupid
整体陈述也相当简单
我通常用解析函数来做这个。但是,以下内容可能在Oracle中起作用,至少对于日期算法起作用的数据集是如此:
select id, min(date) as date_from, max(date) as date_to
from (select (date - rownum) as groupid,
t.*
from t
order by id, date
)
group by id, groupid
为什么有人投了反对票???如果你问我这是个好问题,我同意oracle的分析功能,看看它们,它们非常强大。@sinisa229mihajlovski:我猜是有人投了反对票,因为这个问题没有暗示OP尝试过任何东西。这让问题看起来像是请为我做我的工作,不管事实是否如此。
select id, min(date) as date_from, max(date) as date_to
from (select (date - rownum) as groupid,
t.*
from t
order by id, date
)
group by id, groupid