2014-12-19 3 views
5

Я пытаюсь вычислить 28-дневную движущуюся сумму в BigQuery с использованием функции LAG.BigQuery SQL для 28-дневного скользящего оконного агрегата (без записи 28 строк SQL)

Верхний ответ на этот вопрос

Bigquery SQL for sliding window aggregate

от Фелипе Хоффа указывает на то, что, что вы можете использовать функцию LAG. Примером этого может служить:

SELECT 
    spend + spend_lagged_1day + spend_lagged_2day + spend_lagged_3day + ... + spend_lagged_27day as spend_28_day_sum, 
    user, 
    date 
FROM (
    SELECT spend, 
     LAG(spend, 1) OVER (PARTITION BY user ORDER BY date) spend_lagged_1day, 
     LAG(spend, 2) OVER (PARTITION BY user ORDER BY date) spend_lagged_2day, 
     LAG(spend, 3) OVER (PARTITION BY user ORDER BY date) spend_lagged_3day, 
     ... 
     LAG(spend, 28) OVER (PARTITION BY user ORDER BY date) spend_lagged_day, 
     user, 
     date 
    FROM user_spend 
) 

Есть ли способ сделать это, не выписывая 28 строк SQL!

ответ

21

Документация BigQuery не очень помогает объяснить сложность оконных функций, поддерживаемых инструментом, поскольку она не указывает, какие выражения могут появляться после ROWS или RANGE. Он фактически поддерживает стандарт SQL 2003 для функций окна, который вы можете найти в других местах в Интернете, например here.

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

SELECT spend, 
     SUM(spend) OVER (PARTITION BY user ORDER BY date ROWS BETWEEN 27 PRECEDING AND CURRENT ROW), 
     user, 
     date 
FROM user_spend; 

RANGE bound также может быть чрезвычайно полезным. Если в вашей таблице отсутствовали даты для некоторого пользователя, тогда 27 строк PRECEDING вернутся более чем на 27 дней, но RANGE создаст окно, основанное на самих значениях даты. В следующем запросе поле даты является BigQuery TIMESTAMP, а диапазон указан в микросекундах. Я бы посоветовал, что всякий раз, когда вы делаете математику в таком виде в BigQuery, вы тщательно проверяете ее, чтобы убедиться, что она дает вам ожидаемый ответ.

SELECT spend, 
     SUM(spend) OVER (PARTITION BY user ORDER BY date RANGE BETWEEN 27 * 24 * 60 * 60 * 1000000 PRECEDING AND CURRENT ROW), 
     user, 
     date 
FROM user_spend; 
Смежные вопросы