Замените коррелированный подзапрос соединением - PullRequest
0 голосов
/ 13 сентября 2018

Я хотел бы заменить следующий фрагмент ABAP OpenSQL (в предложении where гораздо большего оператора) эквивалентным соединением.

... AND tf~tarifart = ( SELECT MAX( tf2~tarifart ) FROM ertfnd AS tf2 WHERE tf2~tariftyp = e1~tariftyp AND tf2~bis >= e1~bis AND tf2~ab <= e1~ab ) ...

Моя мотивация: миграция запросов к представлениям ABAP CDS (в основном простой SQL с несколько сниженной выразительностью). Увы, коррелированные подзапросы и операторы EXISTS не поддерживаются.

Я немного погуглил и нашел возможное решение (последнее сообщение) здесь https://archive.sap.com/discussions/thread/3824523

Однако предложение

  1. Выбор MAX (значение)
  2. Ваш сценарий использует внутреннее соединение с первым представлением CDS

не работает в моем случае.

  1. tf.bis (и tf.ab) должны находиться в списке выбора нового представления, чтобы ограничить относительное время соединения (нового представления) правильными временными рамками.
  2. Увы, может быть несколько (не перекрывающихся) подкадров (содержащихся в [tf.ab, tf.bis]) с одним и тем же tf.tarifart. Так как они не могут быть сгруппированы вместе, это приводит к нескольким строкам в правой части.

Исходный запрос не имеет проблем с этим (без объединения -> без декартовых произведений).

Я надеюсь, что следующая скрипка (рабочий пример) немного прояснит ситуацию: http://sqlfiddle.com/#!9/8d1f48/3

Учитывая эти ограничения, мне кажется, что эквивалентное соединение действительно невозможно. Предложения или даже подтверждения?

1 Ответ

0 голосов
/ 24 сентября 2018
select doc_belzart,
       doc_tariftyp,
       doc_ab,
       doc_bis,
       max(tar_tarifart)
  from 
  (
    select document.belzart as doc_belzart, 
           document.tariftyp as doc_tariftyp,  
           document.ab as doc_ab,
           document.bis as doc_bis, 
           tariff.tarifart as tar_tarifart,
           tariff.tariftyp as tar_tariftyp,
           tariff.ab as tar_ab,
           tariff.bis as tar_bis
      from dberchz1 as document
      inner join ertfnd as tariff
        on tariff.tariftyp = document.tariftyp and
           tariff.ab <= document.ab and
           tariff.bis >= document.bis
  ) as max_tariff
  group by doc_belzart,
          doc_tariftyp,
          doc_ab,
          doc_bis

В переводе на английский вы, похоже, хотите определить максимально применимый тариф для комплекта документов.

Я бы перестроил это на отдельные шаги:

  1. Определите все применимые тарифы, то есть все тарифы, которые полностью покрывают временной интервал документа. Это станет вашим первым просмотром CDS, и в моем ответе будет сформирован подзапрос.

  2. Определите для всех документов максимально применимый тариф. Это сформирует ваше второе представление CDS, а в моем ответе сформирует внешний запрос. У этого есть MAX / GROUP BY, чтобы уменьшить набор результатов до одного для документа.

...