2014-12-19 7 views
5

Próbuję obliczyć 28-dniową sumę ruchomą w BigQuery za pomocą funkcji LAG.BigQuery SQL dla 28-dniowego agregatora okien przesuwnych (bez pisania 28 wierszy kodu SQL)

Górny odpowiedź na to pytanie

Bigquery SQL for sliding window aggregate

od Felipe Hoffa oznacza, że ​​można użyć funkcji opóźnienia. Przykładem może być:

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 
) 

Czy można to zrobić bez konieczności wypisywania 28 wierszy kodu SQL!

Odpowiedz

21

Dokumentacja BigQuery nie ułatwia wyjaśnienia złożoności funkcji okna obsługiwanych przez narzędzie, ponieważ nie określa, jakie wyrażenia mogą pojawiać się po WIERSZACH lub RANGE. W rzeczywistości obsługuje standard SQL 2003 dla funkcji okna, które można znaleźć udokumentowane inne miejsca w Internecie, takie jak here.

Oznacza to, że można uzyskać pożądany efekt za pomocą funkcji pojedynczego okna. Zakres wynosi 27, ponieważ jest to liczba wierszy przed bieżącym, które należy uwzględnić w sumie.

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

Ograniczenie RANGE może być bardzo przydatne. Jeśli w tabeli brakowało dat dla jakiegoś użytkownika, 27 wierszy PRECEDING powróciłoby później niż 27 dni, ale RANGE utworzy okno na podstawie wartości daty. W poniższym zapytaniu pole daty to TIMESTAMP BigQuery, a zakres jest określony w mikrosekundach. Radziłbym, aby zawsze, gdy robisz randkę w ten sposób w BigQuery, dokładnie testujesz to, aby upewnić się, że daje oczekiwaną odpowiedź.

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;