Поиск другой строки на основе текущей строки в той же таблице в Oracle

Предположим, что у меня есть таблица с тремя столбцами:

  1. Идентификатор события (ПК)
  2. Название тэга
  3. ТегЗначение

Мне нужно создать запрос, который приводит к чему-то вроде:

  1. Идентификатор события
  2. Название тэга
  3. ТегЗначение
  4. Тег предыдущего состояния
  5. ПредыдущееУсловиеЗначение

Где PreviousConditionTag/Value берется из TagName и TagValue предыдущей строки (при упорядочении по EventID).

В более простой версии этой проблемы PreviousConditionTag всегда был таким же, как TagName, то есть мне нужно было получить только предыдущее значение для текущего TagName. Я решил это, используя аналитическую функцию Oracle LAG, разбивая по TagName.

Однако теперь мне нужно выполнить что-то подобное, но для случаев, когда PreviousConditionTag является произвольным тегом, связанным с TagName другой таблицей, где связь между TagName и PreviousConditionTag не является однозначной.

Например, если данная строка имеет TagName «ABC», таблица отношений может сказать, что мне нужно найти предыдущее значение либо «IJK», либо «XYZ».

Я смог придумать эту логику в функции Oracle, которая выполняет SELECT для той же таблицы и ищет MAX(EventID), который соответствует критериям. Например:

SELECT * FROM MyTable WHERE EventID = (
    SELECT MAX(EventID) FROM MyTable WHERE TagName IN (
        SELECT ConditionTagName FROM ConditionMappingTable WHERE TagName = [CurrentTagName]
    )
) AND EventID <= [CurrentEventId]

Однако, как вы понимаете, поскольку этот запрос выполняется в функции для каждой строки MyTable, меня беспокоит его производительность.

Я пытался придумать способ снова использовать аналитику Oracle LAG, но я не был уверен, как придумать для нее предложение PARTITION, так как кажется, что разделы перекрываются. (например, тег ABC должен учитывать IJK и XYZ, а тег DEF должен учитывать IJK и UVW)

Любые идеи?


person acee    schedule 29.05.2012    source источник


Ответы (1)


Это переписанная форма ответа, теперь, когда я лучше ее понимаю.

Вы хотите найти перекрывающиеся наборы тегов и получить предыдущий идентификатор события. Идея заключается в следующем:

  1. Добавьте в таблицу сопоставления идентификатор для всех текущих тегов (так что текущий тег = тег условия)
  2. Присоединяйтесь к таблице сопоставления на основе тега condition, чтобы получить совпадающие текущие теги. Таким образом, строки перемаркируются с помощью «текущего» тега, которому они соответствуют, и вы можете использовать это для задержки.
  3. Получите самый последний EventId на основе логики задержки, разбив его по тегу Current.
  4. Выберите результаты, в которых теги «Текущий» и «Условие» совпадают.

    select t.*
    from (select t.*, mt.CurrentTagName, mt.ConditionTagName,
             lag(EventId, 1, NULL)
             over (partition by mt.CurrentTagName
                   order by EventId)
      from t join
           (select CurrentTagName, ConditionTagName
            from ((select CurrentTagName, ConditionTagName
                   from ConditionMappingTable mt
                  ) union all
                  (select distinct CurrentTagName, CurrentTagName
                   from ConditionMappingTable mt
                  )
                 ) mt
           )
           on mt.ConditionTagName = t.tagname
     ) t
    on CurrentTagName = ConditionTagName
    

Это может показаться нелогичным, потому что вы смотрите на вещи в обратном направлении, по условию, а не по текущему состоянию. И вы умножаете количество обрабатываемых строк. Тем не менее, это может быть быстрее, чем решение для соединения, которое вы использовали.

person Gordon Linoff    schedule 29.05.2012
comment
Какова цель смещения в этом случае? Аналитика Oracle LAG() имеет смещение, которое я могу указать, и в простом случае, когда мне просто нужно было предыдущее значение для данного тега, смещение было равно 1. В этом случае смещение по-прежнему технически равно 1, но разделы не т как прямо вперед. В необработанных данных предыдущий тег, который я ищу, мог появиться в любом количестве предшествующих строк (он не всегда появляется непосредственно перед текущей строкой при упорядочении по идентификатору события). - person acee; 29.05.2012
comment
Мои извинения. Я лучше понял вопрос и повторно ответил на него. Возможно, я получил ConditionTagName и CurrentTagName наоборот. - person Gordon Linoff; 29.05.2012
comment
Нет проблем, спасибо за второй взгляд! Ваше предложение выполнить поиск в обратном направлении по условию, а не по текущему значению, похоже, имеет большое значение. Я переписал свой запрос, чтобы сделать это, и теперь он выполняется менее чем за секунду, а не за 5 или 6 секунд до этого. Спасибо за вашу помощь! - person acee; 29.05.2012