Сравните таблицу с собой в plsql - PullRequest
2 голосов
/ 17 декабря 2011

У меня есть таблица дефектов, которая выглядит так:

Ref# ID# Severity Status    Found_Date Verified_Date   Resolve_Date 
1001 21  2        Verified  6/19/2011  6/25/2011
1001 21  2        Verified  6/19/2010  9/18/2011
1001 21  3        Fixed     6/19/2010  10/12/2011      10/12/2011

В этой системе пользователь может ввести запись, которая будет иметь Verified_Date (как в строке 1).

Позже пользователь может вернуться в систему и внести изменения, и система сгенерирует новую запись с теми же Ref# и ID#, однако у нее будет другая Verified_Date (как в строке 2).

Чтобы сделать его еще более сложным, пользователь может вернуться в систему и изменить значение Severity, которое сгенерирует третью запись, и эта запись будет иметь еще другую Verified_Date, но она будет иметь то же самое Ref# и "ID#.

Мне было поручено написать запрос, который вернет следующий результат:

          Initial   Final                       Initial      Final
Ref# ID#  Severity  Severity  Status  Found_Dt  Verified_Dt  Verified_Dt  Resolve_Dt 
1001 21   2         3         Fixed   6/19/2011 9/18/2011    10/12/2011   10/12/2011

Предполагается, что приведенная выше запись является результатом запроса, в котором будут перечислены все записи, в которых произошли изменения Severity, и будет представлена ​​их в вышеуказанном формате с указанием Initial_Verified_Dt, Final_Verified_Dt, Initial_Severity и Final_Severity. Я написал запрос, чтобы сравнить таблицу с самой собой и вернуть все значения, где ID# было одинаковым, но severity отличается. Проблема в том, что я получаю следующий результат:

          Initial   Final                        Initial      Final
Ref# ID#  Severity  Severity  Status  Found_Dt   Verified_Dt  Verified_Dt  Resolve_Dt 
1001 21   2         3         Fixed   6/19/2011  9/18/2011    10/12/2011   10/12/2011
1001 21   3         2         Fixed   6/19/2011  9/18/2011    10/12/2011   10/12/2011
1001 21   2         3         Fixed   6/19/2011  10/12/2011   9/18/2011    10/12/2011
1001 21   3         2         Fixed   6/19/2011  10/12/2011   9/18/2011    10/12/2011

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

Ответы [ 2 ]

1 голос
/ 04 февраля 2012

Я думаю, это то, что вам нужно:

SELECT *
FROM   (
           SELECT ref#
                , id#
                , LAG( severity ) OVER ( PARTITION BY ref#, id# ORDER BY verified_date ) AS initial_severity
                , severity AS final_severity
                , status
                , found_date
                , LAG( verified_date ) OVER ( PARTITION BY ref#, id# ORDER BY verified_date ) AS initial_verified_date
                , verified_date AS final_verified_date
                , resolve_date
           FROM   defects
       )
WHERE  initial_severity <> final_severity
ORDER  BY ref#
        , id#
        , final_verified_date;

Функция LAG() позволяет вам проверить предыдущую строку в наборе курсора / результата (я предположил, что столбец Verified_date можно безопасно использовать для заказазаписи в хронологическом порядке);так что вы можете легко проверить, было ли изменение после предыдущей записи того же дефекта.Точно так же функция LEAD() позволяет вам проверить следующую строку в курсоре.

1 голос
/ 17 декабря 2011

Ни в коем случае это не элегантное решение, но оно работает:

select   REF#
        ,ID#
        ,INITIAL_SEVERITY
        ,FINAL_SEVERITY
        ,STATUS
        ,FOUND_DT
        ,INITIAL_VERIFIED_DT
        ,FINAL_VERIFIED_DT
        ,RESOLVE_DT
from     (select REF#
                ,ID#
                ,(select SEVERITY
                  from   DEFECT D2
                  where  D2.REF# = D.REF#
                         and D2.ID# = D.ID#
                         and VERIFIED_DATE = (select min(VERIFIED_DATE) from DEFECT))
                   as INITIAL_SEVERITY
                ,(select SEVERITY
                  from   DEFECT D2
                  where  D2.REF# = D.REF#
                         and D2.ID# = D.ID#
                         and VERIFIED_DATE = (select max(VERIFIED_DATE) from DEFECT))
                   as FINAL_SEVERITY
                ,(select STATUS
                  from   DEFECT D2
                  where  D2.REF# = D.REF#
                         and D2.ID# = D.ID#
                         and VERIFIED_DATE = (select max(VERIFIED_DATE) from DEFECT))
                   as STATUS
                ,min(FOUND_DATE) over (partition by REF#) as FOUND_DT
                ,(select min(VERIFIED_DATE)
                  from   DEFECT D2
                  where  D2.REF# = D.REF# and D2.ID# = D.ID# and D2.STATUS = 'Verified')
                   as INITIAL_VERIFIED_DT
                ,(select max(VERIFIED_DATE)
                  from   DEFECT D2
                  where  D2.REF# = D.REF# and D2.ID# = D.ID# and D2.STATUS = 'Verified')
                   as FINAL_VERIFIED_DT
                ,(select max(RESOLVE_DATE)
                  from   DEFECT D2
                  where  D2.REF# = D.REF# and D2.ID# = D.ID# and D2.STATUS = 'Fixed')
                   as RESOLVE_DT
          from   DEFECT D)
group by REF#
        ,ID#
        ,INITIAL_SEVERITY
        ,FINAL_SEVERITY
        ,STATUS
        ,FOUND_DT
        ,INITIAL_VERIFIED_DT
        ,FINAL_VERIFIED_DT
        ,RESOLVE_DT

Если вы используете pl / sql, вы можете поместить все эти маленькие подвыборы в функции, если хотите. Я сделал выбор, чтобы упростить группировку.

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