#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
after1
. - Когда первая строка
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