Сообщения

Алгоритм проверки качества истории

Качество истории в исторической таблице можно проверить простым алгоритмом, сумма длины периодов действия равна общей длине истории. Реализация алгоритма на Oracle: WITH T_CITY AS (SELECT 1 ID_C, 'Москва' CITY, DATE '1900-01-01' BEG_DT, DATE '1990-01-01' END_DT FROM DUAL UNION SELECT 1 ID_C, 'Омск' CITY, DATE '1990-01-01' BEG_DT, DATE '2999-01-01' END_DT FROM DUAL UNION SELECT 2 ID_C, 'Томск' CITY, DATE '1900-01-01' BEG_DT, DATE '2999-01-01' END_DT FROM DUAL ) SELECT ID_C FROM T_CITY GROUP BY ID_C --PK HAVING SUM(ABS((END_DT - BEG_DT))) <> MAX(END_DT) - MIN(BEG_DT);

Алгоритм GREATEST-LEAST

Если возникает задача построения истории из двух и более таблиц содержащих историю изменений состояний, то можно воспользоваться алгоритмом соединения двух и более исторических таблиц GREATEST-LEAST. Алгоритм очень чувствительный к качеству истории соединяемых таблиц. Алгоритм очень легко понять на примере приведенном внизу. В примере история начинается с 1900 года и заканчивается 2999 годом. В определенных случаях если при соединении будет использоваться LEFT JOIN то как пример GREATEST будет выглядеть так 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 (SELEC...

ETL (от англ. Extract, Transform, Load)

Изображение
ETL (от англ. Extract, Transform, Load — дословно «извлечение, преобразование, загрузка») — один из основных процессов в управлении хранилищами данных, который включает в себя: извлечение данных из внешних источников  их трансформация и очистка  и загрузка их в хранилище данных  С точки зрения процесса ETL, архитектуру хранилища данных можно представить в виде трёх частей: источник данных: содержит структурированные данные в виде таблиц, совокупности таблиц или просто файла (данные в котором разделены символами-разделителями) промежуточная область: содержит вспомогательные таблицы, создаваемые временно, и, исключительно для организации процесса выгрузки получатель данных: хранилище данных или база данных, в которую должны быть помещены извлечённые данные Перемещение данных от источника к получателю называют потоком данных. Требования к организации потока данных описывается аналитиком. ETL следует рассматривать не только как процесс переноса данных из о...

Балансировка потоков в Oracle

При параллельной загрузке данных в хранилище, чтобы уменьшить время общей загрузки таблиц часто применяется динамическая балансировка по потокам. То есть, разные задачи группируются в какое то количество потоков (обычно константа, но может также меняться в зависимости от разных условий). Выходит что на основании веса разбиваем задачи на несколько потоков, желательно чтобы  максимальный суммарный вес одного потока был минимальным. Итак получается:  Задача о ранце (рюкзаке)  ( англ.   Knapsack problem )  .  Но приведу более простой алгоритм, может и не самый эффективный, но простой и удобный в реализации. Весом могут быть разные параметры,  например: время загрузки в прошлый раз количество строк размер таблицы статистике Балансировку можно делать каждый раз, или в какой то период, и каждый раз задача может попадать в разные потоки. Реализация алгоритма на Oracle: WITH --элементы с весом или продолжительностью ITEMS AS ...

Динамическое получение диапазона дат партиций Oracle

Получить динамический диапазон дат в партициях можно из поля  HIGH_VALUE  в таблице  USER_TAB_PARTITIONS.   Но тут возникают проблемы что поле  HIGH_VALUE имеет тип LONG и не совсем удобно с ним работать не прибегая к помощи PLSQL. Но данную проблему легко решить воспользовавшись функцией  DBMS_XMLGEN.GETXMLTYPE                  Реализация алгоритма на Oracle: SELECT TABLE_NAME, PARTITION_NAME, PARTITION_POSITION, CASE WHEN PARTITION_NAME='PMAX' THEN TO_DATE('2999-12-31 00:00:00', 'yyyy-mm-dd hh24:mi:ss')+1 ELSE TO_DATE(TRIM('''' FROM REGEXP_SUBSTR(EXTRACTVALUE(DBMS_XMLGEN. GETXMLTYPE('select high_value from user_tab_partitions where table_name=''' || TABLE_NAME || ''' and partition_name = ''' || PARTITION_NAME || ...

Олимпиадная задача по Oracle

Вчера упала интересная задача, которая сводится до элементарной, которая аналогичная олимпиадной задаче Oracle. Хочу ее вынести сюда, и показать ее решение на базе алгоритма "схлопывания". Итак, есть таблица: EFF_DTTM EXP_DTTM 01.01.2013 05.01.2013 05.01.2013 08.01.2013 08.01.2013 09.01.2013 11.01.2013 15.01.2013 15.01.2013 25.01.2013 28.01.2013 30.01.2013 Нужно склеить подряд идущие даты и вывести их границы. То есть ожидаемый результат: EFF_DTTM EXP_DTTM 28.01.2013 30.01.2013 11.01.2013 25.01.2013 01.01.2013 09.01.2013 Алгоритм более сложный чем необходимо для такого упрощенного случая, но при реальном использовании появятся еще и бизнес поля, тогда алгоритм подойдет очень хорошо. Так как для схлопывания с учетом дырок в истории понадобится еще учет изменения бизнес полей. Реализация алгоритма на Oracle: WITH --исходные данные T0 AS ( SELECT TO_DATE('01.01.2013', 'DD.MM.YYYY')EFF_DTTM, TO_DATE('05.01.2013', 'DD.MM.Y...

Алгоритм "Схлопывание" (Сollapse)

Встречается ситуация когда история создается но не несет какой либо полезной информации, или может даже мешать. Например у сущности  с определенным ключом есть поле которое часто меняется но нам не нужно грузить его в хранилище. Например мы строим в хранилище связку [Абонент]-> [ФИО] (которое может менятся), а в таблице источника есть например поле [Город] изменения которого влияют на историю. Реализация алгоритма на Oracle: WITH --таблица с историей и ключом из двух полей hist_table AS (SELECT 1 AS KEY, 'Иванов' fio,'Москва' city, DATE '2010-01-01' AS eff_dttm, DATE '2011-01-01' AS exp_dttm FROM dual UNION SELECT 1 AS KEY, 'Иванов' fio,'Киев' city, DATE '2011-01-01' AS eff_dttm, DATE '2014-01-01' AS exp_dttm FROM dual UNION SELECT 1 AS KEY, 'Петров' fio, 'Киев' city, DATE '2014-01-01' AS eff_dttm, DATE '2999-12-31' AS exp_dttm FRO...