Как сравнить старую и предыдущую строки и получить измененные данные только в sql с использованием Lag

#sql #oracle #oracle-sqldeveloper

#sql #Oracle #oracle-sqldeveloper

Вопрос:

У меня есть таблица xx_asg со структурой :

 person_id  grade_id effective_start_date effective_end_date
1            null       28-Jan-97             28-Jan-16
1            35         29-Jan-16             31-Dec-4712
6            35         12-Jun-93             31-Jul-93
6            35         01-Aug-93             30-Sep-99
  

Я должен выяснить, есть ли какие-либо изменения в grade_id путем сравнения предыдущей строки со следующей строкой.
Если есть изменение, мне нужно получить новый столбец с флагом ‘Y’
, а также effective_start_date нового класса. Я попытался создать следующий запрос :

 SELECT  *
From    (
        Select  Person_id,
   Grade_Id,
                LAG(grade_id) OVER (PARTITION BY person_ID ORDER BY effective_start_Date) AS prev_grade_line1,
                Row_Number() Over (Partition By Person_Id Order By Effective_Start_Date Desc) As Rn,
                Effective_Start_Date
                        From    xx_asg
  --WHERE   person_ID = 3
        )
Where   Rn = 1
order by person_id

;
  

Но этот запрос также возвращает prev_grade_line1 и новый идентификатор класса как нулевой или тот же :

введите описание изображения здесь

 Output should look like :

person_id  grade_id prev_grade_id effective_start_date Flag
1            null       35             29-Jan-97        Y         
6            35         35             NULL             NULL


OR 

ONLY CHAGED ROW 
person_id  grade_id prev_grade_id effective_start_date Flag
1            null       35             29-Jan-97        Y    
  

При использовании :

введите описание изображения здесь

Этот запрос также возвращает первую строку. То есть он обрабатывает предыдущий ggrade первой строки как null. В реальном времени есть только 3 изменения, но этот запрос возвращает четыре изменения

введите описание изображения здесь

Комментарии:

1. как должен выглядеть результат?

2. Спасибо за вопрос. Я обновил его.

Ответ №1:

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

 select t.*, 'Y' flag
from (
select  
Person_id,
Grade_Id,
LAG(grade_id) OVER(PARTITION BY person_ID ORDER BY effective_start_Date) prev_grade_line1,
Effective_Start_Date,
row_Number() Over(Partition By Person_Id Order By Effective_Start_Date) As rn
from xx_asg
) t
where nvl(grade_id,10000000) <> nvl(prev_grade_line1,10000000) 
and rn > 1
  

Комментарии:

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

2. см. Редактирование. это также будет обрабатывать значения null .. однако убедитесь, что значение, используемое в nvl , является значением, которого нет в столбце grade . null в текущей строке и null в предыдущей строке будут рассматриваться как без изменений.

3. Это также не работает.. я обновляю свой ответ скриншотом, чтобы показать вам результат

4. Спасибо @vkp. Затем отображается дополнительный последний столбец. Как и в последней строке: для идентификатора человека 8 grade_id как 24 и previous_grade_id как null

5. я изменил row number расчет. ранее это было заказано effective_start_date desc . вы это заметили? попробуйте последнюю версию.