Выбрать 5 последних уведомлений с неактивным статусом в рамках одного SELECT?

Мне нужно ВЫБРАТЬ 5 последних уведомлений, связанных с оборудованием, но мне также нужно проверить, что статус DLFL (I0076 - флаг удаления) не активен ИЛИ не существует.

Я думаю, это должно быть довольно просто, но меня немного смущает тот факт, что статус DLFL имеет 3 возможных варианта.

  1. Существует в таблице JEST с неактивным флагом INITIAL.
  2. Существует в таблице JEST с неактивным флагом = "X". -> Действительная запись
  3. Не существует в таблице JEST. -> Действительная запись

Мне удалось получить только последние 5, выбрав все уведомления истории, а затем удалив те, у которых статус DLFL активен, как в приведенном ниже коде, но это означает, что я выбираю сотни строк за последние 20 лет, чтобы использовать только 5 .

Как бы вы этого избежали?

SELECT qmnum, erdat, stat FROM viqmel
  LEFT OUTER JOIN jest ON jest~objnr = viqmel~objnr
                      AND jest~inact = @abap_false
                      AND jest~stat  = 'I0076'
  WHERE viqmel~equnr = @equi "Input parameter
    AND viqmel~kzloesch = @abap_false
  ORDER BY erdat DESCENDING
  INTO TABLE @DATA(equi_notifs).

DATA equi_notifs_valid LIKE equi_notifs.
LOOP AT equi_notifs ASSIGNING FIELD-SYMBOL(<equi_notif>) WHERE stat IS INITIAL.
  equi_notifs_valid = VALUE #( BASE equi_notifs_valid ( <equi_notif> ) ).
  IF lines( equi_notifs_valid ) >= 5.
    EXIT.
  ENDIF.
ENDLOOP.

person RaTiO    schedule 11.11.2019    source источник


Ответы (1)


Ваш второй цикл не имеет смысла, поскольку вы присоединяетесь только к тем JEST строкам, которые имеют неактивный I0076 статус, что делает логическую ошибку, поэтому оборудование без статуса I0076 вообще не попадает в ваш набор данных, и ваше условие цикла никогда не выполняется.

Решение состоит в том, чтобы переместить условие статуса в WHERE и произвести там фильтрацию.

Почему бы не использовать конструкцию НЕ СУЩЕСТВУЕТ?

SELECT qmnum, erdat, stat FROM viqmel
  LEFT OUTER JOIN jest ON jest~objnr = viqmel~objnr
 WHERE viqmel~kzloesch = @abap_false
   AND ( jest~inact = @abap_true
   AND   jest~stat  = 'I0076' ) OR
  NOT EXISTS ( SELECT * FROM jest WHERE jest~objnr = viqmel~objnr AND jest~stat = 'I0076' )
  ORDER BY erdat DESCENDING
  INTO TABLE @DATA(equi_notifs)
  UP TO 5 ROWS.

Кроме того, добавление UP TO N ROWS устраняет вашу уродливую петлю. .

Кстати, вы упомянули, что вам нужны только восстановленные линии оборудования, не так ли? Почему вы использовали abap_false с inact, наверное, это должно быть abap_true?

person Suncatcher    schedule 11.11.2019
comment
Привет, я думаю, что мой второй цикл имеет смысл, я его тестировал. Мой SELECT - это LEFT OUTER JOIN, поэтому строки с активным I0076 будут иметь значение в поле STAT, а строки, в которых статус не найден или неактивен, не будут иметь значения. Я протестировал его, и, похоже, он работает, получая одну строку, даже если есть несколько статусов. Я уже пробовал решение, подобное тому, что указано в вашем SELECT, но оно не работает, потому что таблица JEST может иметь другой статус, поэтому она возвращает по одной строке для каждого статуса, отличного от I0076, даже для уведомлений, для которых включено I0076. На мой взгляд, мой код работает, но неэффективен. - person RaTiO; 12.11.2019
comment
Это зависит от набора данных, я не могу проверить ваш случай, так как моя таблица qmel не допускает нескольких уведомлений для одного и того же objnr, что странно. Опубликуйте образец набора данных для проверки - person Suncatcher; 12.11.2019
comment
QMEL/VIQMEL имеет только 1 запись на objnr, но таблица JEST имеет несколько, и когда вы выполняете LEFT OUTER JOIN + NOT EXISTS, тогда SELECT возвращает запись для каждого JEST статуса, отличного от I0076. Вот почему мне пришлось сначала выбрать все записи, а затем отфильтровать, если статус активен, чтобы получить только 5 действительных, более поздних. - person RaTiO; 13.11.2019
comment
QMEL/VIQMEL only has 1 record per objnr тогда подход с датой не имеет смысла, ты выбираешь не 5 последних статусов для objnr, а 5 уведомлений для разных objnr, что бессмысленно. Я не могу представить себе использование такого набора - person Suncatcher; 13.11.2019
comment
Извините, я неправильно объясняюсь. Но мой образец SELECT получает все уведомления, связанные с идентификатором оборудования @equi. Тогда LOOP принимает только 5 самых последних со статусом DLFL неактивным. Я бы хотел не выбирать сначала все связанные уведомления и напрямую получать 5 самых последних действительных, но мне это еще не удалось. Я не хочу выбирать какой-либо статус, они мне нужны только для фильтрации, мой ожидаемый конечный результат - это действительный список из 5 идентификаторов уведомлений. - person RaTiO; 13.11.2019