Заменить коррелированный подзапрос на соединение

Я хотел бы заменить следующий фрагмент 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. Selecting MAX(value)
  2. Your scenarion using inner join to first CDS view

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

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

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

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

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

Привет. Это часто задаваемые вопросы по sql, просто Google повторно использует соединение подзапроса вместо in или существует или скалярный подзапрос. Пожалуйста, прочтите и действуйте в соответствии с минимальный воспроизводимый пример. Пожалуйста, сделайте свой пост самодостаточным, цитируйте соответствующие части из ссылки, которая имеет отношение к вашему вопросу. Как поиск в Google названия и вариантов вам не помог? Непонятно, что вы пытаетесь сказать, «вернуть одну строку на максимум» - вы имеете в виду, что это не коррелировано, одно и то же значение используется для каждой строки tf? Как связанное предложение не работает? Можете ли вы объяснить свои ограничения, например, «страх» и «не могу сгруппироваться»?

philipxy 14.09.2018 09:47

Поддержите philipx / Разместите свой запрос полный, а не этот бесполезный кусок

Suncatcher 14.09.2018 13:17

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

user462982 14.09.2018 15:27

Предложение: Создайте второе представление CDS, которое выполняет группировку MAX. Затем присоедините исходный выбор к другому представлению.

Florian 14.09.2018 16:10

Как бы я сделал это без "group by" на tf2 ~ bis? Мне нужен tf2 ~ bis, чтобы определить правильный MAX (tf2 ~ tarifart) для определенной даты ...

user462982 14.09.2018 16:33

Еще один часто задаваемый вопрос - сделать это без группы. Пожалуйста, всегда гуглите много четких, кратких и конкретных версий / формулировок вашего вопроса / проблемы / цели с вашими конкретными строками / именами и без них и читайте много ответов. Добавьте в поисковые запросы релевантные ключевые слова, которые вы обнаружите. Если вы не нашли ответа, отправьте сообщение, используя поиск по одному из вариантов по заголовку и ключевым словам для тегов. См. Текст при наведении курсора мыши на стрелку "против". PS наибольшее число n на группу PS Google 'stackexchange notifications' повторно уведомляет непостера среди нескольких комментаторов через @имя пользователя. PS Пожалуйста: поясните написание и включите код и цитаты.

philipxy 22.09.2018 12:27
0
6
2 048
1

Ответы 1

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, чтобы уменьшить набор результатов до одного на документ.

Другие вопросы по теме