Могу ли я выбрать несколько таблиц в одном запросе WITH? - PullRequest
2 голосов
/ 25 марта 2020

У меня длинный запрос со структурой with. В конце я хотел бы вывести две таблицы. Это возможно?

(кстати, таблицы и запросы в снежинке SQL.)

Код выглядит так:

with table_a as (
               select id, 
                      product_a
               from x.x ),
     table_b as (
               select id, 
                      product_b
               from x.y ),
     table_c as ( 

..... many more alias tables and subqueries here .....

             )

select * from table_g where z = 3 ;

Но для самой последней строки, Я хотел бы запросить table_g дважды, один раз с z = 3 и один раз с другим условием, поэтому в результате я получаю две таблицы. Есть ли способ сделать это (заканчивая двумя запросами, а не одним), или мне нужно заново выполнить весь код для каждой таблицы, которую я хочу выводить?

Ответы [ 2 ]

3 голосов
/ 25 марта 2020

Один запрос = один набор результатов. Это просто способ работы RDBMS.

CTE (оператор WITH) - это просто синтаксис c сахар для подзапроса.

Например, запрос, похожий на ваш:

with table_a as (
               select id, 
                      product_a
               from x.x ),
     table_b as (
               select id, 
                      product_b
               from x.y ),
     table_c as (     
               select id, 
                      product_c
               from x.z ),

select * 
from table_a
   inner join table_b on table_a.id = table_b.id
   inner join table_c on table_b.id = table_c.id;

На 100% идентичен:

select *
from
  (select id, product_a from x.x) table_a
  inner join (select id, product_b from x.y) table_b
      on table_a.id = table_b.id
  inner join (select id, product_c from x.z) table_c
      on table_b.id = table_c.id

Версия CTE не предоставляет никаких дополнительных функций которые не доступны в не-cte версии (за исключением рекурсивного cte), и путь выполнения будет на 100% одинаковым (РЕДАКТИРОВАТЬ: Пожалуйста, смотрите ответ и комментарий Саймона ниже, где он отмечает, что Snowflake может материализовать производную таблицу определяется CTE, так что он должен выполнить этот шаг только один раз, если в основном запросе на него ссылаются несколько раз Таким образом, до сих пор нет способа получить второй набор результатов из одного запроса.

2 голосов
/ 25 марта 2020

Хотя синтаксически они одинаковы, у них нет одинакового плана производительности.

Первый случай может быть, когда один из этапов в CTE является дорогостоящим и повторно используется через другие CTE или объединение во многих случаях, под Snowflake, используйте их как CTE. Я вижу, что он запускает «дорогую» часть только один раз, что может быть хорошо, например, вот так.

WITH expensive_select AS (
    SELECT a.a, b.b, c.c
    FROM table_a AS a
    JOIN table_b AS b
    JOIN table_c AS c
    WHERE complex_filters
), do_some_thing_with_results AS (
    SELECT stuff
    FROM expensive_select
    WHERE filters_1
), do_some_agregation AS (
    SELECT a, SUM(b) as sum_b
    FROM expensive_select
    WHERE filters_2
)
SELECT a.a
    ,a.b
    ,b.stuff
    ,c.sum_b
FROM expensive_select AS a
LEFT JOIN do_some_thing_with_results AS b ON a.a = b.a
LEFT JOIN do_some_agregation AS c ON a.a = b.a;

Первоначально это было развернуто. и дорогой частью были некоторые ВИДЫ о том, что фильтр диапазона дат, который был применен на верхнем уровне, не сдвигался вниз (из-за оконных функций), что приводило к многократному сканированию таблицы. Когда их толкали в CTE, стоимость была оплачена один раз. (В нашем случае размещение фильтров диапазона дат в CTE заставило Snowflake заметить фильтры и вывести их в представление, и все может измениться, через несколько недель исходный код работал так же хорошо, как и модифицированный, поэтому они «исправлены» "что-то)

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

Я также использую подобные CTE, чтобы облегчить чтение кода, но дать CTE значимое имя, но псевдоним для чего-то короткого, для использования. Очень люблю это.

...