Вложенный подзапрос в FOR ALL ENTRIES

Консультант прислал мне этот пример кода, вот что он ожидает получить

SELECT m1~vbeln_im m1~vbelp_im m1~mblnr smbln      
    INTO CORRESPONDING FIELDS OF TABLE lt_mseg
    FROM mseg AS m1
    INNER JOIN mseg AS m2 ON m1~mblnr = m2~smbln
                         AND m1~mjahr = m2~sjahr
                         AND m1~zeile = m2~smblp
    FOR ALL ENTRIES IN lt_vbfa
    WHERE 
      AND m2~bwart = '102'
      AND 0 = ( select SUM( ( CASE
        when SHKZG = 'S' THEN 1
        when SHKZG = 'H' THEN -1
        else 0
        END ) *MENGE ) MENGE
        into lt_mseg-summ
        from mseg
        where
        VBELN_IM = m1~vbeln_im
        and VBELP_IM = m1~vbelp_im
        ).

Проблема в том, что я не понимаю, как это должно работать в текущем синтаксисе. Я думаю о том, чтобы получить внутренний выбор и использовать его как условие для основного, но есть ли правильный способ написать эту вложенную конструкцию?

Насколько я понимаю, если вложенный оператор = 0, то выполняется основной запрос. Проблема здесь в случае внутри вложенного оператора. Возможно ли это вообще в ABAP? И, на мой взгляд, эту проверку можно было бы использовать вне основного SQL-запроса.

Любые предложения приветствуются.


person AlexanderK    schedule 22.03.2016    source источник
comment
Поделитесь (поэтапно): четко объясните, каковы ваши намерения + с какой проблемой вы столкнулись + что вы делали до этого.   -  person Asif Mehmood    schedule 22.03.2016
comment
Как я понял - если вложенный оператор = 0, тогда выполняется основной запрос, проблема здесь - случай внутри вложенного оператора, возможно ли это даже в ABAP? И логика подсказывает, что эту проверку можно было использовать вне основного SQL-запроса. Но я новичок в ABAP, поэтому оставляю место для других возможных объяснений.   -  person AlexanderK    schedule 22.03.2016
comment
Отредактируйте свой вопрос (добавьте эту информацию в свой POST), чтобы другие могли помочь!   -  person Asif Mehmood    schedule 22.03.2016
comment
Оператор Case возможен, но я не вижу здесь смысла в конструкции FOR ALL ENTRIES. Он используется для выбора из таблицы БД на основе зависимой itab, которой в вашем случае нет. Я не вижу зависимости между вашими lt_vbfa и mseg таблицами. Вы должны четко сформулировать свою задачу.   -  person Suncatcher    schedule 22.03.2016
comment
И не пишите такой код, просто чтобы показать, что вы можете читать и писать древнеиндийские иероглифы ниндзя на санскрите. Никто не будет грустить, если Вы разделите этот монстр select, и, кроме того, Вы также используете для всех записей функции условного агрегирования, ou ou ou. Путь к тяжелому. Это правильно, что Вы перекладываете тяжелую работу на ДБ, хорошо, но даже для этого есть ограничения, и Вы уже на грани.   -  person icbytes    schedule 22.03.2016
comment
Извините за чрезмерное цитирование, единственное, что меня действительно беспокоит - это вложенный запрос. Со всем остальным - работает нормально.   -  person AlexanderK    schedule 22.03.2016


Ответы (2)


предоставленная вам логика является частью Native / Open SQL и имеет некоторые недостатки, о которых вам необходимо знать.

  1. оператор, который вы показываете, должен быть помещен между EXEC SQL и ENDEXEC.
  2. логика зависит от платформы.
  3. между EXEC и ENDEXEC не выполняется проверка синтаксиса
  4. выполнение этого обходит процесс буферизации базы данных, поэтому он медленнее

Для меня я бы исследовал лучший способ захвата данных, который лучше работает за пределами открытого / собственного sql.

Если вы хотите продвигаться вперед с такой логикой, ниже приведены несколько полезных ссылок. Существует пример выбора с использованием вложенного выбора с оператором case. Тестовая программа Пример логики

person Aleuskiris    schedule 26.03.2016

Наверное, это то, что вам нужно, работает как минимум с ABAP 750.

SELECT vbeln UP TO 100 ROWS
 FROM vbfa
 INTO TABLE @DATA(lt_vbfa).

DATA(rt_vbeln) = VALUE range_vbeln_va_tab( FOR GROUPS val OF <line> IN lt_vbfa GROUP BY ( low = <line>-vbeln ) WITHOUT MEMBERS ( sign = 'I' option = 'EQ' low = val-low ) ).

SELECT m1~vbeln_im, m1~vbelp_im, m1~mblnr, m2~smbln
  INTO TABLE @DATA(lt_mseg)
  FROM mseg AS m1
  JOIN mseg AS m2
    ON m1~mblnr = m2~smbln
   AND m1~mjahr = m2~sjahr
   AND m1~zeile = m2~smblp
 WHERE m2~bwart = '102'
   AND m1~vbeln_im IN ( SELECT vbelv FROM vbfa WHERE vbelv IN @rt_vbeln  )
 GROUP BY m1~vbeln_im, m1~vbelp_im, m1~mblnr, m2~smbln
HAVING SUM( CASE  m1~shkzg WHEN 'H' THEN 1  WHEN 'S' THEN -1 ELSE 0 END * m1~menge ) = 0.

Да, агрегирование и FOR ALL ENTRIES невозможно в одном SELECT, но вы можете обмануть систему с помощью диапазона и подзапроса. Также вам не нужны три объединения для суммирования перевернутых документов, ваш подзапрос SUM здесь избыточен.

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

person Suncatcher    schedule 23.03.2020