Oracle LEAD — возвращает следующее соответствующее значение столбца

У меня есть данные ниже в одной таблице.

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

И я хочу получить СЛЕДУЮЩИЕ данные из столбца OUT. Поэтому в приведенном ниже запросе используется функция LEAD.

SELECT ROW_NUMBER,TIMESTAMP,IN,OUT,LEAD(OUT) OVER (PARTITION BY NULL ORDER BY TIMESTAMP) AS NEXT_OUT 
FROM MYTABLE;

Он дает данные, как показано ниже в столбце NEXT_OUT.

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

Но мне нужно знать соответствующее значение следующего столбца последовательно, как столбцы DESIRED. Пожалуйста, дайте мне знать, как я могу добиться этого в Oracle LEAD FUNCTION

СПАСИБО


person usersam    schedule 21.02.2019    source источник
comment
IGNORE NULLS может работать для row_number 3, но не работает для row_number 4.   -  person usersam    schedule 21.02.2019


Ответы (2)


Присвойте номер строки всем IN и OUT отдельно, отсортируйте результаты, поместив их в один столбец, и рассчитайте LEAD:

WITH cte AS (
    SELECT t.*
         , CASE WHEN "IN"  IS NOT NULL THEN COUNT("IN")  OVER (ORDER BY "TIMESTAMP") END AS rn1
         , CASE WHEN "OUT" IS NOT NULL THEN COUNT("OUT") OVER (ORDER BY "TIMESTAMP") END AS rn2
    FROM t
)
SELECT cte.*
     , LEAD("OUT") OVER (ORDER BY COALESCE(rn1, rn2), rn1 NULLS LAST) AS NEXT_OUT
FROM cte
ORDER BY COALESCE(rn1, rn2), rn1 NULLS LAST

Демонстрация на db‹>скрипке

person Salman A    schedule 21.02.2019
comment
Спасибо @Салман. Это работает с (ORDER BY COALESCE(rn1, rn2), rn1). - person usersam; 21.02.2019
comment
как позаботиться о том, чтобы одна запись OUT была вставлена ​​без IN, например, INSERT INTO t (ROW_NUMBER, TIMESTAMP, IN, OUT) VALUES (0, 100, NULL, '100'). У меня также есть некоторые неверные данные в таблице. - person usersam; 21.02.2019
comment
in row следует ставить перед out, поэтому , r1 NULLS LAST является правильным. re: неверные данные... Понятия не имею, но, вероятно, нужна другая логика; опережение/отставание может не справиться с этим. - person Salman A; 21.02.2019

Перечислите «входящие» и «исходящие» и используйте эту информацию для сопоставления.

select tin.*, tout.out as next_out
from (select t.*,
             count(in) over (order by timestamp) as seqnum_in
      from t
     ) tin left join
      (select t.*,
             count(out) over (order by timestamp) as seqnum_out
      from t
     ) tout
     on tin.in is not null and
        tout.out is not null and
        tin.seqnum_in = tout.seqnum_out;
person Gordon Linoff    schedule 21.02.2019
comment
Спасибо @Гордон. Это будет работать, но данные, показанные в ques, являются фиктивными данными из таблицы, размер которой будет очень большим. мы не можем позволить себе доступ к таблице дважды с левым соединением. - person usersam; 21.02.2019
comment
@usersam . . . Я бы посоветовал вам попробовать это, прежде чем сразу же отвергать ответ. - person Gordon Linoff; 21.02.2019