Динамические PIVOT в SQL с помощью Snowflake

Простые в использовании динамические опорные точки в Snowflake: как использовать и создавать внутри хранимую процедуру JavaScript.

Есть что-то в SQL и PIVOT: каждый хочет PIVOT своих результатов, но, кажется, нет простого способа для этого. К счастью, у пользователей Snowflake есть собственный способ выполнения сводных операций в SQL с помощью функции PIVOT ():

select *
from (
  select * from table(result_scan(last_query_id(-1)))
)
pivot(max(pivot_value)
for pivot_column in ('Spider-Man', 'Wonder Woman', 'Iron Man'))

Тем не менее, у PIVOT () в Snowflake есть одно ограничение: пользователям необходимо явно вызывать значения столбцов, в которые нужно выполнить поворот. Затем пользователи переходят в Stack Overflow, чтобы спросить как заставить Snowflake предоставлять PIVOT () с динамическими столбцами, и, похоже, нет однозначного ответа.

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

Как получить динамические пивоты в Snowflake

  1. Напишите запрос, который объединяет данные, которые вы хотите сводить. Обязательно определите столбец с pivot_values ​​и столбец с pivot_columns:
select name
  , date_trunc(quarter, month) pivot_column
  , sum(month_views) pivot_value 
from hero_views
group by 1,2

2. Вызовите хранимую процедуру pivot_prev_results():

call pivot_prev_results();

3. Теперь найдите свои сводные результаты, просмотрев вывод этой хранимой процедуры:

select *
from table(result_scan(last_query_id(-2)));

Вот и все!

Теперь, если вы хотите вместо этого вращаться по их именам, просто повторите процесс, переключая имена столбцов в первом запросе:

  1. Запрос
select name pivot_column
  , date_trunc(quarter, month) month
  , sum(month_views) pivot_value
from hero_views
group by 1,2

2. Вызов хранимой процедуры

call pivot_prev_results();

3. Найдите результаты:

select *
from table(result_scan(last_query_id(-2)));

Создание хранимой процедуры

Если вы хотите вызвать pivot_prev_results(), сначала вам нужно его создать. Это исходный код:

Крутые уловки, заставляющие pivot_prev_results() работать:

Давайте рассмотрим хранимую процедуру, чтобы выявить несколько интересных идей в Snowflake:

create or replace procedure pivot_prev_results()

да. Вы можете определить хранимые процедуры в Snowflake.

returns string

Чтобы эта хранимая процедура работала, нам не нужно ничего возвращать, но мы можем использовать это позже.

language javascript

Это круто: хранимые процедуры в Snowflake могут быть определены в JavaScript, что открывает целый мир возможностей.

execute as caller

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

as
$$

Мы используем «$$» для ограничения кода JavaScript. $$ позволяет нам избежать более сложного побега изнутри.

var cols_query = `
select ‘\\’’
|| listagg(distinct pivot_column, ‘\\’,\\’’) within group (order by pivot_column)
|| ‘\\’’
from table(result_scan(last_query_id(-1)))`;

Это запрос, который позволит нам определить столбцы в результирующей сводной таблице.

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

Ключевая концепция Snowflake. Запросы Snowflake выполняются в рамках сеанса, что позволяет вам обращаться к предыдущим запросам, результатам и даже устанавливать переменные сеанса.

Чтобы получить все различные значения в столбце pivot_column, мы используем listagg(distinct pivot_column), а чтобы убедиться, что они выглядят отсортированными в конечном результате, мы добавляем within group(order by pivot_column).

Затем мы выполняем запрос внутри процедуры. Что круто, Snowflake предоставляет среде JavaScript UDF API, поэтому код JS может просить Snowflake выполнять запросы:

var stmt1 = snowflake.createStatement({sqlText: cols_query});
var results1 = stmt1.execute();
results1.next();

Результатом этого запроса является список столбцов, которые мы собираемся использовать, чтобы запросить у Snowflake точку поворота:

var col_list = results1.getColumnValue(1);

Затем нам просто нужно создать простой запрос PIVOT () в Snowflake, используя значения столбцов, которые мы только что выяснили:

pivot_query = `
select *
from (select * from table(result_scan(last_query_id(-2))))
pivot(max(pivot_value) for pivot_column in (${col_list}))
`
var stmt2 = snowflake.createStatement({sqlText: pivot_query});
stmt2.execute();

Обратите внимание, что в этом запросе используется max (pivot_value). Идея состоит в том, что предыдущий запрос, запущенный пользователем, будет агрегировать результаты любым способом, которым они хотят, и на этом шаге мы должны выбрать не более одного значения для агрегирования.

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

return `select * from table(result_scan(‘${stmt2.getQueryId()}’));\n select * from table(result_scan(last_query_id(-2)));`;
$$;

Обратите внимание, что пользователи найдут результаты с last_query_id(-2), потому что -1 - это результаты вызова хранимой процедуры.

Удачных поворотов!

Хочу больше?

Я Фелипе Хоффа, защитник облачных данных для Snowflake. Спасибо, что присоединились ко мне в этом приключении. Вы можете следить за мной в Twitter и проверять reddit.com/r/snowflake, чтобы узнать самые интересные новости о Snowflake.