Рекурсивное обновление в Snowflake

#sql #data-science #etl #snowflake-cloud-data-platform #data-analysis

#sql #наука о данных #etl #snowflake-облачная платформа данных #анализ данных

Вопрос:

У меня есть таблица для разных пользователей в snowflake. Мне нужно обновить столбец значений, если есть значение ‘Z’. Z будет заменен ближайшим значением, отличным от Z, от этого пользователя.

Оригинальная таблица:

 | User | Order | Value |
| ---- | ------| ----- |
| A    | 1     |  X    |
| A    | 2     |  Y    |
| A    | 3     |  Z    |
| A    | 4     |  Z    |
| A    | 5     |  W    |
| A    | 6     |  Z    |
| B    | 1     |  Y    |
| B    | 2     |  Z    |
| B    | 3     |  Z    |
 

Целевая таблица:

 | User | Order | Value |
| ---- | ------| ----- |
| A    | 1     |  X    |
| A    | 2     |  Y    |
| A    | 3     |  Y    |
| A    | 4     |  Y    |
| A    | 5     |  W    |
| A    | 6     |  W    |
| B    | 1     |  Y    |
| B    | 2     |  Y    |
| B    | 3     |  Y    |
 

Я написал рекурсивный запрос на обновление. Но исходная таблица содержит миллионы строк. Это потребовало бы очень большого количества рекурсии, что недопустимо в Snowflake. Есть ли какой-либо другой способ, которым я мог бы достичь своей цели? Я думаю о функции window, но не имею представления о том, как ее реализовать.

Ответ №1:

Вы можете использовать lag(ignore nulls) , чтобы получить предыдущее значение, которое вы хотите. Тогда вы можете использовать join :

 update original o
    set value = prev_value
    from (select o.*,
                 lag(case when value <> 'Z' then value end ignore nulls) over (partition by user order by order) as prev_value
          from original o
         ) o2
    where o.value = 'Z' and
          o2.user = o.user and
          o2.order = o.user