Sql 基于Startdate和enddate拆分记录
输入集Sql 基于Startdate和enddate拆分记录,sql,oracle,Sql,Oracle,输入集 CMP BND_CD STARTDATE ENDDATE 01 UF 03/15/2010 07/01/2010 01 TRL 03/15/2010 12/15/2014 虚拟数据 CREATE TABLE DATA ( CMP, BND_CD, STARTDATE, ENDDATE ) AS SELECT '01','UF', DATE '2010-03-15', DATE '2010-07-01' FROM DUAL UNION ALL SELECT
CMP BND_CD STARTDATE ENDDATE
01 UF 03/15/2010 07/01/2010
01 TRL 03/15/2010 12/15/2014
虚拟数据
CREATE TABLE DATA ( CMP, BND_CD, STARTDATE, ENDDATE ) AS
SELECT '01','UF', DATE '2010-03-15', DATE '2010-07-01' FROM DUAL UNION ALL
SELECT '01','TRL', DATE '2010-03-15', DATE '2010-12-15' FROM DUAL;
我需要输出为3条记录,这将分割TRL/UF记录,即
CMP BND_CD STARTDATE ENDDATE
01 UF 03/15/2010 07/01/2010
01 TRL 03/15/2010 07/01/2010
01 TRL 07/01/2010 12/15/2014
如果日期范围相互重叠,则应为两张BND_CD的每个CMP代码进行拆分。我们必须根据CMP值对记录进行分组,如果TRL与UF重叠,则应拆分TRL reords,如果UF与TRL重叠,则应拆分UF记录。查询:
SELECT u.cmp, -- UF values preceding the TRL range
u.bnd_cd,
u.start_date,
LEAST( u.end_date, t.start_date )
FROM data t
INNER JOIN
data u
ON ( t.bnd_cd = 'TRL'
AND u.bnd_cd = 'UF'
AND t.cmp = u.cmp
AND u.start_date < t.start_date )
UNION ALL
SELECT u.cmp, -- UF values within the TRL range
u.bnd_cd,
GREATEST( u.start_date, t.start_date ),
LEAST( u.end_date, t.end_date )
FROM data t
INNER JOIN
data u
ON ( t.bnd_cd = 'TRL'
AND u.bnd_cd = 'UF'
AND t.cmp = u.cmp
AND u.start_date <= t.end_date
AND u.end_date >= t.start_date )
UNION ALL
SELECT u.cmp, -- UF values following the TRL range
u.bnd_cd,
GREATEST( u.start_date, t.end_date ),
u.end_date
FROM data t
INNER JOIN
data u
ON ( t.bnd_cd = 'TRL'
AND u.bnd_cd = 'UF'
AND t.cmp = u.cmp
AND u.end_date > t.end_date )
UNION ALL
SELECT t.cmp, -- TRL values preceding the UF range
t.bnd_cd,
t.start_date,
LEAST( t.end_date, u.start_date )
FROM data t
INNER JOIN
data u
ON ( t.bnd_cd = 'TRL'
AND u.bnd_cd = 'UF'
AND t.cmp = u.cmp
AND t.start_date < u.start_date )
UNION ALL
SELECT t.cmp, -- TRL values within the UF range
t.bnd_cd,
GREATEST( t.start_date, u.start_date ),
LEAST( t.end_date, u.end_date )
FROM data t
INNER JOIN
data u
ON ( t.bnd_cd = 'TRL'
AND u.bnd_cd = 'UF'
AND t.cmp = u.cmp
AND t.start_date <= u.end_date
AND t.end_date >= u.start_date )
UNION ALL
SELECT t.cmp, -- TRL values following the UF range
t.bnd_cd,
GREATEST( t.start_date, u.end_date ),
t.end_date
FROM data t
INNER JOIN
data u
ON ( t.bnd_cd = 'TRL'
AND u.bnd_cd = 'UF'
AND t.cmp = u.cmp
AND t.end_date > u.end_date )
CMP BND_CD START_DATE END_DATE
--- ------ ---------- ----------
01 UF 2010-03-15 2010-07-01
01 TRL 2010-03-15 2010-07-01
01 TRL 2010-07-01 2010-08-01
如果您有更多行,例如另一行的start/end=04/01/2010-08/01/2010会怎么样?@Aleksej那么我们应该再创建一个间隔,作为新记录。我们必须根据CMP值对记录进行分组,然后如果TRL与UF重叠,则应拆分TRL reords,或者如果UF与TRL重叠,则应拆分UF记录。@Aleksej如果将2010年1月4日-2010年1月8日添加为TRL记录,则UF应在2010年1月3日-2010年1月4日、2010年1月1日-2010年1月7日之间拆分。或者,如果将2010年1月4日-2010年1月8日添加为UF记录,则TRL应在2010年1月3日-2010年1月4日,2010年1月4日-2010年1月7日,-2010年1月7日-2010年1月8日,2014年1月8日-2010年1月12日之间进行拆分。@TomJMuthirenthi请不要在注释中添加测试用例-将它们编辑到答案中。我用样本数据编辑了你的答案,但我不能100%确定你的预期结果是什么;因此,请编辑我留下问号以澄清的区域。@TomJMuthirenthi最好是问你想要回答的问题(并包括适当的边缘案例),而不是回答你实际提出的不能完全解决你问题的问题。就目前情况而言,您的第一个示例非常简单,解决的答案几乎肯定不适用于后两种更复杂的情况-因此,如果您只想解决简单的情况,请回滚我的编辑(或重新编辑),但如果您的问题更复杂,请提供适当的信息。