2017-02-22 46 views
0

У меня есть таблица EMPLOYEE со следующими полями:нужно добавить данные в таблицу, только если последние данные (последняя на основе самого высокой даты) для записи не существует

ENROLL_DATE EMP ID EMP_NAME DEPT SWITCH 
01-20-2001 123  ABC  D1  N 
01-20-2012 123  ABC  D2  N 
10-12-2016 123  RST  D2  N 
02-10-2017 123  RST  D3  N 
02-10-2017 456  TYU  D2  N 

У меня есть другая таблица EMPLOYE_CUR

ENROLL_DATE EMP ID EMP_NAME DEPT SWITCH 
02-23-2017 123  PQR  D4  N 
02-23-2017 456  TYU  D2  Y 

мне нужно вставлять записи в таблице СОТРУДНИК только если его новая запись (New будет запись изменена для EMP_ID или EMP_NAME или DEPT, даже если ПЕРЕКЛЮЧАТЕЛЬ изменяется мы не будут вставлять эту запись) мы будем сравнением reocrd для emp_ID для hisgest ENROLL_DATE. Поэтому, если запись будет изменена на основе последней записи для emp_ID в таблице EMPLOYEE, тогда только мы будем вставлять эту запись. Таким образом, в вышеописанном случае записи, которые должны быть вставлены являются:

ENROLL_DATE EMP ID EMP_NAME DEPT SWITCH 
02-23-2017 123  PQR  D4  N 

Так таблица сотрудников теперь будет:

ENROLL_DATE EMP ID EMP_NAME DEPT SWITCH 
01-20-2001 123  ABC  D1  N 
01-20-2012 123  ABC  D2  N 
10-12-2016 123  RST  D2  N 
02-10-2017 123  RST  D3  N 
02-19-2017 123  RST  D4  Y 
02-23-2017 123  PQR  D4  N 

Я пытался сделать это с помощью курсора, получая все записи образуют РАБОТНИКОВ таблицу с самым высоким Enroll_date, а затем подумать, чтобы сравнить это с таблицей EMPLOYEE_CUR, но не мог понять, как это сделать.

Может ли кто-нибудь помочь мне с запросом здесь?

Спасибо!

+0

* изменено для EMP_ID *, вероятно, слишком много. Новый EMP_ID является простым новым сотрудником, у вас нет шансов, что ваша таблица распознает chnage из EMP_ID (для этого потребуется дополнительный столбец PREVIOUS_EMP_ID) –

+0

. Посмотрите на таблицу 'EMPLOYEE_CUR', последние две строки. Представьте, что 'EMP_NAME' был' PQR' в обоих (вместо перехода от 'RST' к' PQR'). В таком случае вы все равно вставляете обе строки? Если нет, какой из них вы вставляете - только более ранний? (Это был бы наиболее логически согласованный ответ) – mathguy

+0

И, в любом случае, НЕ делайте этого в PL/SQL-процедуре; независимо от правильного и полного требования, вы можете сделать все это в простом SQL, с гораздо большей эффективностью и ремонтопригодностью. – mathguy

ответ

0

Здесь вы найдете упрощенное решение, которое должно дать вам совет, как обрабатывать ваши возможные особые случаи.

Обратите внимание, что я предполагаю, что общая история идентична в обеих таблицах и что в обеих таблицах будет создан новый сотрудник .

Если это не так, вы мачете уточните запрос, чтобы обратиться к нему.

Решение состоит из двух частей:

1) фильтр простоя записи в EMPLOYE_CUR, что соответствует без изменений (например, только ПЕРЕКЛЮЧАТЕЛЬ изменено) - использовать analytical functions проследить последние значения

2) выберите реальные записи изменений , которые имеют ENROLL_DATE выше, чем MAX (ENROLL_DATE) из таблицы EMPLOYEE

(Последний шаг ВСТАВИТЬ не считается очевидным.) - смотрите ниже

ШАГ 1

with history as (
select ENROLL_DATE, EMP_ID, EMP_NAME, DEPT,SWITCH, 
LAG(EMP_NAME) OVER (PARTITION BY EMP_ID ORDER BY ENROLL_DATE) PREV_EMP_NAME, 
LAG(DEPT) OVER (PARTITION BY EMP_ID ORDER BY ENROLL_DATE) PREV_DEPT 
from EMPLOYE_CUR) 
select 
    ENROLL_DATE, EMP_ID, EMP_NAME, DEPT, SWITCH, 
    case when EMP_NAME != PREV_EMP_NAME or DEPT != PREV_DEPT then 'Y' end is_changed 
from history; 

ENROLL_DATE    EMP_ID EMP_NAME DEPT  SWITCH  IS_CHANGED 
------------------- ---------- ---------- ---------- ---------- ---------- 
20.01.2001 00:00:00  123 ABC  D1   N      
20.01.2012 00:00:00  123 ABC  D2   N   Y   
12.10.2016 00:00:00  123 RST  D2   N   Y   
10.02.2017 00:00:00  123 RST  D3   N   Y   
17.02.2017 00:00:00  123 RST  D3   Y      
19.02.2017 00:00:00  123 RST  D4   Y   Y   
23.02.2017 00:00:00  123 PQR  D4   N   Y 

ШАГ 2

with history as (
select ENROLL_DATE, EMP_ID, EMP_NAME, DEPT,SWITCH, 
LAG(EMP_NAME) OVER (PARTITION BY EMP_ID ORDER BY ENROLL_DATE) PREV_EMP_NAME, 
LAG(DEPT) OVER (PARTITION BY EMP_ID ORDER BY ENROLL_DATE) PREV_DEPT 
from EMPLOYE_CUR), 
clean_history as (
select 
    ENROLL_DATE, EMP_ID, EMP_NAME, DEPT, SWITCH, 
    case when EMP_NAME != PREV_EMP_NAME or DEPT != PREV_DEPT then 'Y' end is_changed 
from history) 
select clean_history.ENROLL_DATE, clean_history.EMP_ID, EMP_NAME, DEPT, SWITCH from clean_history 
join (select EMP_ID, max(ENROLL_DATE) ENROLL_DATE from EMPLOYEE group by EMP_ID) e 
on clean_history.EMP_ID = e.EMP_ID and clean_history.ENROLL_DATE > e.ENROLL_DATE 
where is_changed = 'Y'; 


ENROLL_DATE    EMP_ID EMP_NAME DEPT  SWITCH 
------------------- ---------- ---------- ---------- ---------- 
19.02.2017 00:00:00  123 RST  D4   Y   
23.02.2017 00:00:00  123 PQR  D4   N 
0

Я использовал ниже запрос и его работает отлично , Не уверен, что я охватил все сценарии:

INSERT into EMPLOYEE(ENROLL_DATE, EMP_ID, EMP_NAME, DEPT, SWITCH) 
SELECT ENROLL_DATE, EMP_ID, EMP_NAME, DEPT, SWITCH FROM EMPLOYEE_CUR 
    WHERE NOT EXISTS (SELECT * FROM EMPLOYEE A WHERE A.EMP_ID = EMPLOYEE_CUR.EMP_ID 
    AND A.EMP_NAME = EMPLOYEE_CUR.EMP_NAME 
    AND DEPT= EMPLOYEE_CUR.DEPT 
    AND A.Enroll_date in (SELECT MAX(enroll_date) over (partition by emp_id) as max_date from employee b where a.emp_id=b.emp_id)); 

Может кто-нибудь прокомментировать, если он выглядит правильно?

+0

Это не кажется правильным в следующем случае: для данного 'EMP_ID' ​​самые последние значения' EMPN_NAME' и 'DEPT' в' EMPLOYEE_CUR' совпадают с самыми последними значениями в 'EMPLOYEES', но в факт, что были изменения. Например: с момента последнего обновления для «РАБОТНИКОВ» сотрудник один раз менял отделы, а затем вернулся в первоначальный отдел. Ваш запрос пропустит это. И, с другой стороны, в примере в моем комментарии к вашему вопросу он выберет две строки из «EMPLOYEE_CUR», даже если между этими двумя строками нет изменений **. – mathguy

+0

И вы, кажется, не отфильтровываете «изменить строки» (строки в «EMPLOYEE_CUR»), у которых есть дата ** старше ** самой последней даты (для этого сотрудника) в «РАБОТНИКАХ». Я предполагаю, что для INSERT следует учитывать только такие записи, не так ли? – mathguy

+0

@mathguy вы можете привести пример того, что вы говорите, поскольку я не могу понять, что вы имеете в виду. – Mishti