Есть ли способ получить дополнение к пересечению двух записей в SQL?
Например, у меня есть две записи:
KEY BEG_DATE END_DATE FATHER DEEP
K1 1 jan 30 jun F1 0
K1 1 jan 31 dec F2 1
Я бы хотел получить
KEY BEG_DATE END_DATE FATHER DEEP
K1 1 jan 30 jun F1 0
K1 1 jul 31 dec F2 1
Реальная ситуация такова, что у меня есть организационные подразделения, которые должны относиться к отцу организационных подразделений и могут относиться к центру затрат. Если нет явной связи с МВЗ, текущая организационная единица наследует МВЗ от отца (или его предков ...)
С очень запутанным утверждением я получил результат, но мой SQL не работает в том случае, если у меня есть явное отношение с Cost Center, которое закрыто ДО конца его ссылочной единицы org, и я не могу перейти на один (или более) шаги выше
Просто попробовать SqlFiddle
DDL
CREATE TABLE Org (
IDOrg char(6),
Beg_O DATE,
End_O DATE);
CREATE TABLE Org_REL (
IDOrg char(6),
IDOrgFather char(6),
Beg_OO date,
End_OO date);
CREATE TABLE Org_Cost (
IDOrg char(6),
IDCostCenter char(10),
Beg_OC date,
End_OC date);
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
INSERT INTO Org
SELECT 'Org0', '2018-01-01', '9999-12-31' FROM DUAL UNION
SELECT 'Org1', '2018-01-01', '9999-12-31' FROM DUAL UNION
SELECT 'Org2', '2018-01-01', '9999-12-31' FROM DUAL UNION
SELECT 'Org3', '2018-01-01', '9999-12-31' FROM DUAL UNION
SELECT 'Orgx1', '2018-01-01', '9999-12-31' FROM DUAL UNION
SELECT 'Orgx2', '2018-01-01', '9999-12-31' FROM DUAL UNION
SELECT 'Orgx3', '2018-01-01', '9999-12-31' FROM DUAL ;
INSERT INTO Org_REL
SELECT 'Org1', 'Org0', '2018-01-01', '9999-12-31' FROM DUAL UNION
SELECT 'Org2', 'Org0', '2018-01-01', '9999-12-31' FROM DUAL UNION
SELECT 'Org3', 'Org1','2018-01-01', '2018-06-30' FROM DUAL UNION
SELECT 'Org3', 'Org2','2018-07-01', '9999-12-31' FROM DUAL UNION
SELECT 'Orgx1', 'Org3','2018-01-01', '9999-12-31' FROM DUAL UNION
SELECT 'Orgx2', 'Org3','2018-01-01', '9999-12-31' FROM DUAL UNION
SELECT 'Orgx3', 'Org1','2018-01-01', '9999-12-31' FROM DUAL;
INSERT INTO Org_Cost
SELECT 'Org0', 'Cost0', '2018-01-01', '9999-12-31' FROM DUAL UNION
SELECT 'Org1', 'Cost1', '2018-01-01', '9999-12-31' FROM DUAL UNION
SELECT 'Org2', 'Cost2', '2018-01-01', '9999-12-31' FROM DUAL UNION
SELECT 'Orgx1', 'Cost_x1', '2018-01-01', '9999-12-31' FROM DUAL UNION
SELECT 'Orgx3', 'Cost_x3', '2018-01-01', '2018-07-31' FROM DUAL ;
DML
select
CONNECT_BY_ROOT Org.IDOrg LEAF,
Org_REL.IDOrg,
Org_REL.IDOrgFather,
Org_REL.Beg_OO Beg_OO,
Org_REL.End_OO End_OO,
level DEEP,
SYS_CONNECT_BY_PATH(Org_REL.IDOrg, '*') path
from
Org
LEFT OUTER JOIN Org_REL on Org.IDOrg = ORG_Rel.IDOrg
WHERE 1=1
CONNECT BY --NOCYCLE
PRIOR Org_REL.IDOrgFather = Org_REL.IDOrg
UNION
SELECT
IDOrg, null, IDOrg, BEG_O, END_O, 0, '*' || IDOrg
FROM Org
)
,
final as (
select
LEAF, PATH, DEEP, IdOrgFather, IDCostCenter,
TO_CHAR(CASE
WHEN t.Beg_OO < oc.Beg_OC THEN oc.Beg_OC
ELSE t.Beg_OO
END, 'YYYY-MM') BEGVAL,
TO_CHAR(CASE
WHEN t.End_OO > oc.End_OC THEN oc.End_OC
ELSE t.End_OO
END, 'YYYY-MM') ENDVAL
, RANK() OVER (PARTITION BY LEAF ORDER BY DEEP) ORD
from
tree t left outer join
Org_Cost oc on t.IDOrgFather = oc.IDOrg
WHERE
IDCostCenter is not null
)
--SELECT * FROM FINAL WHERE leaf = 'Orgx3'
select
LEAF, IDCostCenter, BEGVAL, ENDVAL, ORD
from final
WHERE
LEAF IN ('Orgx1', 'Orgx2', 'Orgx3')
AND ORD = 1
я получаю следующие записи
| LEAF | IDCOSTCENTER | BEGVAL | ENDVAL | ORD |
|--------|--------------|---------|---------|-----|
| Orgx1 | Cost_x1 | 2018-01 | 9999-12 | 1 |
| Orgx2 | Cost1 | 2018-01 | 2018-06 | 1 |
| Orgx2 | Cost2 | 2018-07 | 9999-12 | 1 |
| Orgx3 | Cost_x3 | 2018-01 | 2018-07 | 1 |
из которых
- первый в порядке (явные отношения)
- второе и третье в порядке (нет явного отношения, наследуют для иерархии)
- четвертое частично верно, потому что я хотел бы также наследственное отношение после '2018-07
если я удалю предложение AND ORD = 1
, которое я получу (только для orgx3)
| LEAF | IDCOSTCENTER | BEGVAL | ENDVAL | ORD |
|--------|--------------|---------|---------|-----|
| Orgx3 | Cost_x3 | 2018-01 | 2018-07 | 1 |
| Orgx3 | Cost1 | 2018-01 | 9999-12 | 2 |
| Orgx3 | Cost0 | 2018-01 | 9999-12 | 3 |
, где первая запись уже захвачена, но вторая должна начинаться не с 2018-01, а с 2018-08