Oracle SQL Запрос слияния для устранения проблемы целостности данных - PullRequest
0 голосов
/ 19 февраля 2020
create table abc
(
job_id integer
,etl_job_run_day date
,cust_sid integer
,cust_id number(38,0)
,cust_first_name varchar2(100)
,cust_last_name varchar2(100)
,effective_dt_from date
,effective_dt_to date
,version integer
,latest_fl varchar2(1)
,actual_cust_id integer
);

insert into abc values (123,01.01.2020,100,6842,'Tony','Greig',10.01.2020 00:00:00,31.12.2199 23:59:59,1,'Y','');
insert into abc values (123,01.01.2020,123,6842,'Tony','Greig',10.01.2020 00:00:00,31.12.2199 23:59:59,1,'Y',9011);
JOB_ID  ETL_JOB_RUN_DAY    CUST_SID CUST_ID CUST_FIRST_NAME CUST_LAST_NAME   EFFECTIVE_DATE_FROM   EFFECTIVE_DATE_TO    VERSION LATEST_FL ACTUAL_CUST_ID
123 01.01.20 00:00:00  100      6842    Tony        Greig        10.01.00 00:00:00     31.12.99 23:59:59    1   Y   
123 15.01.20 00:00:00  148      6842    Tony        Greig        10.01.00 00:00:00     31.12.99 23:59:59    1   Y     9011

, так что это неправильно из-за неправильного обновления исторических данных, поэтому ожидаемые значения должны быть такими:

JOB_ID  ETL_JOB_RUN_DAY    CUST_SID CUST_ID CUST_FIRST_NAME CUST_LAST_NAME   EFFECTIVE_DATE_FROM   EFFECTIVE_DATE_TO    VERSION LATEST_FL ACTUAL_CUST_ID
123 01.01.20 00:00:00  100      6842    Tony        Greig        01.01.00 00:00:00     15.01.20 00:00:00    1   N   
123 15.01.20 00:00:00  148      6842    Tony        Greig        15.01.20 00:00:00     31.12.99 23:59:59    2   Y     9011

1 Ответ

0 голосов
/ 19 февраля 2020

Во-первых, нам нужен некоторый первичный ключ, чтобы четко определить порядок строк. Нам нужно сравнить предыдущую и следующую строки, и для этого порядок элементарен. Если мы можем использовать job_id, etl_job_run_day, cust_sid для этого, то вы можете найти проблемные c строки с помощью этого запроса:

select * 
  from (
    select job_id, etl_job_run_day, cust_sid, effective_dt_from edf, effective_dt_to edt, version, latest_fl, 
           lag(latest_fl)  over (partition by job_id order by etl_job_run_day, cust_sid) prev_fl,
           lead(latest_fl) over (partition by job_id order by etl_job_run_day, cust_sid) next_fl,
           lag(effective_dt_to)  over (partition by job_id order by etl_job_run_day, cust_sid) prev_edt,
           lead(effective_dt_to) over (partition by job_id order by etl_job_run_day, cust_sid) next_edt,
           lead(etl_job_run_day) over (partition by job_id order by etl_job_run_day, cust_sid) next_run
      from abc
      where latest_fl = 'Y' )
  where edt in (prev_edt, next_edt)

Пожалуйста, проверьте его, если все в порядке, вы можете использовать вышеуказанный запрос в качестве исходной таблицы в merge :

merge into abc a
using (
    select * 
      from (
        select job_id, etl_job_run_day, cust_sid, effective_dt_from edf, effective_dt_to edt, version, latest_fl, 
               lag(latest_fl)  over (partition by job_id order by etl_job_run_day, cust_sid) prev_fl,
               lead(latest_fl) over (partition by job_id order by etl_job_run_day, cust_sid) next_fl,
               lag(effective_dt_to)  over (partition by job_id order by etl_job_run_day, cust_sid) prev_edt,
               lead(effective_dt_to) over (partition by job_id order by etl_job_run_day, cust_sid) next_edt,
               lead(etl_job_run_day) over (partition by job_id order by etl_job_run_day, cust_sid) next_run
          from abc
          where latest_fl = 'Y' )
      where edt in (prev_edt, next_edt)) s
on (a.job_id = s.job_id and a.etl_job_run_day = s.etl_job_run_day and a.cust_sid = s.cust_sid)
when matched then update set 
    a.latest_fl = case when next_fl = 'Y' then 'N' else a.latest_fl end,
    a.effective_dt_to   = case when next_fl = 'Y' and  next_edt = a.effective_dt_to 
                                then next_run
                                else a.effective_dt_to end,
    a.effective_dt_from = case when prev_fl = 'Y' and  prev_edt = a.effective_dt_to 
                                then etl_job_run_day
                                else a.effective_dt_to end, 
    version = case when prev_fl = 'Y' then version + 1 else version end

dbfiddle

Это дало мне запрошенные значения для ваших (исправленных) выборочных данных. Опять, пожалуйста, проверьте это. Сделайте копию, если это возможно. Если у вас более двух позиций подряд и там всегда одна и та же версия, вам понадобится дополнительное слияние, но в этом случае следует увеличить все последующие версии? Вы можете сделать это, используя count() over (order by...) в следующем подобии merge.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...