Алгоритм GREATEST-LEAST
Если возникает задача построения истории из двух и более таблиц содержащих историю изменений состояний, то можно воспользоваться алгоритмом соединения двух и более исторических таблиц GREATEST-LEAST. Алгоритм очень чувствительный к качеству истории соединяемых таблиц. Алгоритм очень легко понять на примере приведенном внизу. В примере история начинается с 1900 года и заканчивается 2999 годом. В определенных случаях если при соединении будет использоваться LEFT JOIN то как пример GREATEST будет выглядеть так
GREATEST(A.BEG_DT, NVL(B.BEG_DT, A.BEG_DT)) что в принципе тоже будет работать.
Реализация алгоритма на Oracle:
В результате получим:
GREATEST(A.BEG_DT, NVL(B.BEG_DT, A.BEG_DT)) что в принципе тоже будет работать.
Реализация алгоритма на Oracle:
WITH T_MAIN AS
(SELECT 1 ID, 2 ID_F, 4 ID_C, DATE '1900-01-01' BEG_DT, DATE '2000-01-01' END_DT FROM DUAL UNION
SELECT 1 ID, 3 ID_F, 4 ID_C, DATE '2000-01-01' BEG_DT, DATE '2010-01-01' END_DT FROM DUAL UNION
SELECT 1 ID, 3 ID_F, 5 ID_C, DATE '2010-01-01' BEG_DT, DATE '2999-01-01' END_DT FROM DUAL
) ,
T_FIO AS
(SELECT 2 ID_F, 'Вася' FIO, DATE '1900-01-01' BEG_DT, DATE '2001-01-01' END_DT FROM DUAL UNION
SELECT 2 ID_F, 'Петя' FIO, DATE '2001-01-01' BEG_DT, DATE '2999-01-01' END_DT FROM DUAL UNION
SELECT 3 ID_F, 'Иван' FIO, DATE '1900-01-01' BEG_DT, DATE '2999-01-01' END_DT FROM DUAL
) ,
T_CITY AS
(SELECT 4 ID_C, 'Москва' CITY, DATE '1900-01-01' BEG_DT, DATE '1990-01-01' END_DT FROM DUAL UNION
SELECT 4 ID_C, 'Омск' CITY, DATE '1990-01-01' BEG_DT, DATE '2999-01-01' END_DT FROM DUAL UNION
SELECT 5 ID_C, 'Томск' CITY, DATE '1900-01-01' BEG_DT, DATE '2999-01-01' END_DT FROM DUAL
)
SELECT T_MAIN.ID,
T_FIO.FIO,
T_CITY.CITY,
GREATEST(T_MAIN.BEG_DT, T_FIO.BEG_DT, T_CITY.BEG_DT) AS BEG_DT,
LEAST(T_MAIN.END_DT, T_FIO.END_DT, T_CITY.END_DT) AS END_DT
FROM T_MAIN,
T_FIO,
T_CITY
WHERE T_MAIN.ID_F = T_FIO.ID_F
AND T_MAIN.ID_C = T_CITY.ID_C
AND GREATEST(T_MAIN.BEG_DT, T_FIO.BEG_DT, T_CITY.BEG_DT) < LEAST(T_MAIN.END_DT, T_FIO.END_DT, T_CITY.END_DT)
ORDER BY GREATEST(T_MAIN.BEG_DT, T_FIO.BEG_DT, T_CITY.BEG_DT);
В результате получим:
| ID | FIO | CITY | BEG_DT | END_DT | |
|---|---|---|---|---|---|
| 1 | 1 | Вася | Москва | 01.01.1900 | 01.01.1990 |
| 2 | 1 | Вася | Омск | 01.01.1990 | 01.01.2000 |
| 3 | 1 | Иван | Омск | 01.01.2000 | 01.01.2010 |
| 4 | 1 | Иван | Томск | 01.01.2010 | 01.01.2999 |
Комментарии
Отправить комментарий