Oracle SQL: Использование ЗАДЕРЖКИ при отсутствии текущей строки

#sql #oracle #oracle12c

Вопрос:

У меня есть таблица, из которой я пытаюсь извлечь информацию с помощью функции ЗАДЕРЖКИ.

Тип Дата Ценность
A 01 1
A 02 2
B 01 3

Я пытаюсь получить строки по типу со значением за этот месяц и за месяц до этого, так что в идеале:

Тип Дата Значение M Значение M-1
A 02 2 1
B 02 0 3
 SELECT
Type,
Date,
Value as Value M,
LAG (Value,1,0) over(PARTITION BY Type ORDER BY Date) as Value M-1
FROM Table
 

За исключением того, конечно, что, поскольку нет строки для типа B и месяца 02, я не получаю строку для типа B.

У вас есть какие-нибудь предложения?

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

1. Я не понимаю. Ваш запрос не фильтруется, но ваши результаты содержат только две строки, а не три.

2. Если Date это столбец типа данных date , то в примерах показывайте даты, а не строки типа 01 и 02 . (Это строки, а не числа; есть число «1», «01» — это не число.) Мы ответим на ваш вопрос в том виде, в каком он был опубликован, а затем вы вернетесь и измените вопрос, потому что решение работает для целых чисел или строк, но вы не можете напрямую перевести его в даты. Отдельно от этого: решение, скорее всего, будет основано на секционированном внешнем соединении и не будет иметь ничего общего с ЛАГОМ или какой-либо другой аналитической функцией. Не делайте свою попытку ответить частью вопроса.

3. @GordonLinoff Да, хорошо пойман, в моем результате должно было быть 3 строки.

4. @mathguy На самом деле мой столбец даты представляет собой строку в формате «YYYYMM». В итоге я использовал ЛАГ: хитрость заключалась в том, чтобы восстановить всю таблицу без пропущенных строк.

Ответ №1:

Простая задержка, вероятно, не поможет, потому что вам нужно создать запись за последний месяц, если она не существует для данного типа. Если ваша дата хранится в виде целого числа, как в образцах данных, следует учитывать подобный шаблон. Если он хранится как дата, вам нужно будет добавить какой — то рейтинг в соединение или извлечение(месяц с даты) — 1 (будьте осторожны с январем), но это должно дать представление о сути.

 WITH TYPE_LATEST_MONTH AS 
  ( SELECT DISTINCT
           TYPE,
           (SELECT MAX(DATE) FROM TABLE) AS LATEST_MONTH
      FROM TABLE
  )
SELECT TLM.TYPE,
       TLM.LATEST_MONTH AS DATE,
       COALESCE(TLM.VALUE_M, 0) AS VALUE_M,
       COALESCE(TLM_PREV.VALUE_M, 0) AS VALUE_M_MINUS_1
  FROM TYPE_LATEST_MONTH TLM
  LEFT
  JOIN TABLE TBL
    ON TLM.Type = TBL.Type
   AND TLM.LATEST_MONTH = TBL.DATE
  LEFT
  JOIN TABLE TBL_PREV
    ON TLM.Type = TBL_PREV.Type
   AND TLM.LATEST_MONTH = TBL_PREV.DATE - 1
 

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

1. Спасибо вам за ваш ответ! К сожалению, я не мог использовать его оптом, потому что, если присмотреться к нему повнимательнее, таблица усечена на предыдущем шаге, и поэтому мне нужно снова сгенерировать всю историю, но это натолкнуло меня на мысль, что мне нужно это сделать. В своем запросе я делаю перекрестное соединение для разных дат и разных типов, слева соединяю это с таблицей, чтобы получить значения, а затем выполняю задержку в результате. Мне удалось непреднамеренно исправить ошибку в процессе, так что все хорошо 😀