Как сначала запустить подзапрос в presto

#sql #amazon-web-services #amazon-athena #presto #in-clause

Вопрос:

У меня есть следующий запрос:

 select * 
from Table1 
where NUMid in (select NUMid 
                from Table2 
                where email = 'xyz@gmail.com')
 

Мое намерение состоит в том, чтобы получить список всех нумидов из таблицы 2, имеющих значение электронной почты, равное xyz@gmail.com и используйте этот список нумидов для запроса из таблицы 1.

В presto запрос сначала выполняет внешний запрос. Есть ли способ запустить и сохранить результат внутреннего запроса, а затем использовать его во внешнем запросе в presto?

Комментарии:

1. В большинстве версий SQL вы бы индексировали Table2 так, чтобы приведенный выше поиск подзапроса выполнялся очень быстро. Но Presto не поддерживает регулярные индексы, поэтому я не знаю, что здесь можно сделать.

2. Странно, так как внутренний запрос значительно упростил бы внешний запрос! Вы обеспокоены тем, что это занимает много времени? Интересно, будет ли это работать более эффективно, если сделать это через JOIN ?

Ответ №1:

Оптимизатор может делать все, что ему заблагорассудится. В этом случае он должен выполнить внутренний запрос один раз, а затем, по сути, выполнить JOIN операцию (технически «полу-соединение»).

Во многих базах данных exists наличие соответствующих индексов решает проблему производительности.

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

 select t1.* 
from Table1 t1 join
     (select distinct t2.NUMid 
      from Table2 t2
      where t2.email = 'xyz@gmail.com'
     ) t2
     on t1.NUMid = t2.NUMid;
 

Важно select distinct , чтобы join код был эквивалентен in коду. Однако, если вы знаете, что дубликатов нет, это более разговорно написано без подзапроса:

 select t1.* 
from Table1 t1 join
     Table2 t2
     on t1.NUMid = t2.NUMid
where t2.email = 'xyz@gmail.com'
 

Ответ №2:

Presto и Trino (ранее известные как PrestoSQL) выполняют этот запрос как операцию «полусоединения»: он создает индекс в памяти со строками, поступающими из внутреннего запроса, и проверяет строки внешнего запроса на соответствие этому индексу. Если значение присутствует, то выводится строка из внешнего запроса, в противном случае она отфильтровывается.

В последних версиях Trino появилась функция «динамическая фильтрация», которая позволяет механизму запросов динамически фильтровать и удалять данные для внешнего запроса в источнике на основе информации, динамически полученной из внутреннего запроса. Вы можете прочитать больше об этом в этих сообщениях в блоге: