Oracle SQL извлекает предыдущие строки на основе

#sql #oracle12c

#sql #oracle12c

Вопрос:

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

 CARRCD  FLTNBR     IND    DEPDATETIME
----    --------   -----  --------
AB       123       0      2020-10-29T14:00:00
AB       124       0      2020-10-29T10:00:00
AB       119       0      2020-10-29T09:00:00
AB       100       0      2020-10-29T08:00:00
AB       105       1      2020-10-29T07:00:00 ---------> Match 
AB       99        1      2020-10-29T06:00:00
AB       135       1      2020-10-29T04:00:00
AB       178       1      2020-10-29T02:00:00
  

Теперь, когда я получаю вышеуказанный набор данных после объединения нескольких таблиц, мне нужно найти первую запись, чей индекс совпадает с 1, а затем вернуть предыдущую запись. Итак, в приведенном выше наборе данных
первой записью, которая соответствует IND = 1, является «AB 105», а затем я должен вернуть предыдущую запись

 AB       100       0      2020-10-29T08:00:00
  

Пожалуйста, помогите

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

1. Пожалуйста, покажите, что вы пробовали и какую ошибку / неожиданный результат вы получили. Пожалуйста, используйте CTE (с предложением), а не таблицы открытого текста, чтобы указать свои входные данные. Или подготовьте dbfiddle. Это помогает сосредоточиться на ответе вместо форматирования текста. В вашем вопросе отсутствуют важные требования — предыдущая запись в каком порядке (при условии depdatetime desc)? является fltnbr уникальным (при условии, что да)? что делать, если ind в depdatetime порядке убывания встречается несколько последовательностей 0-1-0-1? Кажется, решение будет использоваться lag(ind) over (order by depdatetime desc) , но нет гарантии, что это то, что вы хотите.

2. Спасибо за ваш комментарий. множественные последовательности 0-1-0-1 не будут выполняться, и результат сортируется на основе depdatetime desc. С задержкой я могу получить определенное значение из предыдущей записи, но мне нужно извлечь всю предыдущую строку. . Пожалуйста, исправьте мое понимание

Ответ №1:

Если вы хотите, чтобы это произошло в первый раз, то:

 select t.*
from (select t.*,
             lead(ind) over (order by depdatetime desc) as next_ind
      from t
     ) t
where t.ind = 0 and t.next_ind = 1
order by depdatetime
fetch first 1 row only;
  

Однако я подозреваю, что вы хотите, чтобы это carcd было так. Если это так, вам нужна partition by и еще немного логики:

 select t.*
from (select t.*,
             row_number() over (partition by carcd order by depdatetime) as seqnum
      from (select t.*,
                   lead(ind) over (partition by carcd order by depdatetime desc) as next_ind
            from t
           ) t
      where t.ind = 0 and t.next_ind = 1
     ) t
where seqnum = 1;
  

Обратите внимание, что приведенное выше является довольно общим. В частности, это работает:

  • Когда ind может иметь более двух значений.
  • Когда ind можно вернуться к 0 after 1 .
  • Когда первая строка 1 (которая отклоняется как кандидат).

Если проблема более ограничена, вероятно, есть другие решения.

Ответ №2:

На основе дополнительной информации, предоставленной вами в комментарии, вы можете найти запрошенную строку как ту, которая имеет ind = 0 и за которой следует строка с ind = 1. Это делается с помощью lead аналитической функции.

Предполагая t , что это ваше отношение, этот слепо типизированный SQL должен работать:

 select CARRCD,  FLTNBR,     IND,    DEPDATETIME
from (
  select t.*, lead(IND) over (order by depdatetime desc) next_ind
  from t
) x
where x.ind = 0 and x.next_ind = 1