我写了以下查询,不幸的是它不起作用。我想要实现的是,我每行选择的日期是客户关系的生效日期。
ci_per_per
表包含以下列:
per_id1
,per_id2
,start_dt
,end_dt
per_id1
是父,per_id2
是孩子。
start_dt
和end_dt
定义关系的持续时间
SELECT
CONNECT_BY_ROOT per_id2 AS per_id2,
per_id1,
(CASE WHEN start_dt < (PRIOR start_dt1)
THEN (PRIOR start_dt1)
ELSE start_dt
END) AS start_dt1,
(CASE WHEN end_dt > (PRIOR end_dt1)
THEN (PRIOR end_dt1)
ELSE end_dt
END) AS end_dt1,
level AS "PER_LEVEL"
FROM ci_per_per
CONNECT BY NOCYCLE PRIOR per_id1 = per_id2
我得到的错误是:END_DT1: Invalid identifier.
有没有办法在oracle中实现这个功能?
示例场景:
per_id1 | per_id2 | start_dt | end_dt
-------------------------------------------
B | A | 01-01-2011 | 01-01-2011
C | B | 01-01-2010 | 01-01-2010
E | B | 01-01-2011 | 01-01-2014
D | C | 01-01-2009 | 01-01-2015
现在我希望所有记录都有01-01-2011
作为开始日期。但是,如果层次结构相反(意味着交换per_id_1和Per_id2值),则记录应按原样显示。
请注意,对于上面的示例,我们需要使用带有start with
条件的per_id2='A'
子句运行它。另外,请了解如果使用per_id2='B'
因此,当我从per_id2='B'
开始时,结果应该使所有记录都为01-01-2010
而不是01-01-2011
现在有结束日期,除了带有E的记录和带有A的记录外,所有记录都应为01-01-2011
,其中结束日期为null
(假设我们以A开头)。
答案 0 :(得分:1)
Oracle Hierarchy和CTE的组合将产生您想要的结果:
WITH cte AS
(SELECT
per_id1,
max(connect_by_root start_dt) as max_start,
min(connect_by_root end_dt) as min_end
FROM
ci_per_per
CONNECT BY
NOCYCLE PRIOR per_id1 = per_id2
GROUP BY
per_id1)
SELECT
ci_per_per.per_id1,
ci_per_per.per_id2,
cte.max_start,
cte.min_end
FROM
cte
join ci_per_per on cte.per_id1=ci_per_per.per_id1
请参阅SQLFiddle here您的示例非常简单,因此我无法确定此逻辑是否适用于所有测试用例。
编辑已针对最低end_dt
进行了更新。
答案 1 :(得分:0)
我一直在努力解决这个问题,并找到了解决方案。
如果您认为以下SQL存在任何问题,请纠正我:
select *
from (SELECT root as per_id2,
per_id1,
PER_LEVEL,
(case
when max(connect_by_root start_dt) >= max(start_dt) then
max(connect_by_root start_dt)
else
max(start_dt)
end) as max_start,
(case
when min(connect_by_root end_dt) <= min(end_dt) then
min(connect_by_root end_dt)
else
min(end_dt)
end) AS min_end
FROM (SELECT connect_by_root per_id2 AS root,
per_id1,
per_id2,
level as per_level,
(case
when connect_by_root start_dt >= start_dt then
connect_by_root start_dt
else
start_dt
end) as start_dt,
(case
when connect_by_root end_dt <= end_dt then
connect_by_root end_dt
else
end_dt
end) as end_dt
FROM ci_per_per
CONNECT BY NOCYCLE PRIOR per_id1 = per_id2)
CONNECT BY NOCYCLE PRIOR per_id1 = per_id2
and PRIOR root = root
GROUP BY per_id1, per_id2, root, per_level)
where max_start <= min_end
以下是同一
的fiddle