我有一个支票帐户表,其中包含列Cust_id
(客户ID),Open_Date
(开始日期)和Closed_Date
(结束日期)。每个帐户有一行。客户可以在任何给定时间开设多个帐户。我想知道此人成为客户已有多长时间了。eg1:
CREATE TABLE [Cust](
[Cust_id] [varchar](10) NULL,
[Open_Date] [date] NULL,
[Closed_Date] [date] NULL
)
insert into [Cust] values ('a123','10/01/2019','10/15/2019')
insert into [Cust] values ('a123','10/12/2019','11/01/2019')
理想情况下,我想将此表插入只有一行的表中,即该人从10/01/2019到11/01/2019一直是客户。 (在他关闭前一个帐户之前,他打开了第二个帐户。
类似,例如2:
insert into [Cust] values ('b245','07/01/2019','09/15/2019')
insert into [Cust] values ('b245','10/12/2019','12/01/2019')
在这种情况下,我希望看到两行-表明他是从07/01到09/15的客户,然后又是从10/12到12/01的客户。
您能指出我最佳方法吗?
我将其视为差距和孤岛问题。您想将周期重叠的相邻行分组在一起。
这是使用lag()
和累积值sum()
求解的一种方法。每当打开日期大于上一个记录的关闭日期时,就会开始一个新组。
select
cust_id,
min(open_date) open_date,
max(closed_date) closed_date
from (
select
t.*,
sum(case when not open_date <= lag_closed_date then 1 else 0 end)
over(partition by cust_id order by open_date) grp
from (
select
t.*,
lag(closed_date) over (partition by cust_id order by open_date) lag_closed_date
from cust t
) t
) t
group by cust_id, grp
在[this db fiddle中使用您的示例数据,查询将产生:
cust_id |开放日期|截止日期:------ | :--------- | :----------a123 | 2019-10-01 | 2019-11-01b245 | 2019-07-01 | 2019-09-15b245 | 2019-10-12 | 2019-12-01
您可以尝试类似的方法:
select distinct
cust_id,
(select min(Open_Date)
from Cust as b
where b.cust_id = a.cust_id and
a.Open_Date <= b.Closed_Date and
a.Closed_Date >= b.Open_Date
),
(select max(Closed_Date)
from Cust as b
where b.cust_id = a.cust_id and
a.Open_Date <= b.Closed_Date and
a.Closed_Date >= b.Open_Date
)
from Cust as a
因此,对于每一行-您正在从所有重叠范围中选择最小和最大日期,以后会分别过滤掉重复项