2014-07-24 102 views
5

給定一個帶有一些排序和一些數字的BigQuery表,我想計算一個數字的「移動最大值」 - 類似於移動平均值,但是取代最大值。從Trying to calculate EMA (exponential moving average) using BigQuery看起來最好的方法是使用LEAD(),然後自己進行聚合。 (Bigquery moving average基本上暗示了CROSS JOIN,但是由於數據的大小,這看起來會很慢)。計算BigQuery中的移動最大值

理想情況下,我可能只能從單個重複字段返回而不是20個單獨字段內部查詢,然後使用正常的聚合重複字段,但我還沒有想出一個辦法做到這一點,所以我堅持滾動自己的聚合。雖然這對於總計或平均值來說足夠簡單,但計算最大內聯是相當棘手的,我還沒有想出一個好辦法來做到這一點。 (下面的例子當然是爲了使用公共數據集而設計的,它們也可以在3個元素之間進行滾動,而我想這樣做的時間在20個左右。我已經以編程方式生成了查詢,所以使得它的短是不是一個大問題)

一種方法是做到以下幾點:

SELECT word, 
    (CASE 
    WHEN word_count >= word_count_1 AND word_count >= word_count_2 THEN word_count 
    WHEN word_count_1 >= word_count AND word_count_1 >= word_count_2 THEN word_count_1 
    ELSE word_count_2 END 
    ) AS max_count 
FROM (
    SELECT word, word_count, 
    LEAD(word_count, 1) OVER (ORDER BY word) AS word_count_1, 
    LEAD(word_count, 2) OVER (ORDER BY word) AS word_count_2, 
    FROM [publicdata:samples.shakespeare] 
    WHERE corpus = 'macbeth' 
) 

這是O(n^2),但它至少起作用。我還可以做的IF個嵌套鏈,就像這樣:

SELECT word, 
    IF(word_count >= word_count_1, 
    IF(word_count >= word_count_2, word_count, word_count_2), 
    IF(word_count_1 >= word_count_2, word_count_1, word_count_2)) AS max_count 
FROM ... 

這是O(n)來評估,但查詢的大小是n的指數,所以我不認爲這是一個很好的選擇;肯定會超過n = 20的BigQuery查詢大小限制。我也可以做n個嵌套查詢:

SELECT word, 
    IF(word_count_2 >= max_count, word_count_2, max_count) AS max_count 
FROM (
    SELECT word, 
    IF(word_count_1 >= word_count, word_count_1, word_count) AS max_count 
    FROM ... 
) 

雖然,看起來做20個嵌套查詢可能不是一個好主意。

有沒有一種很好的方法來做這種查詢?如果不是,我是否正確地認爲n在20左右,第一個是最不好的?

回答

7

一招我使用滾動窗口:CROSS JOIN與數表。在這種情況下,爲了有一個3年的移動窗口,我交叉連接數字0,1,2。然後,您可以爲每個組創建一個ID(ending_at_year == year-i),然後按組進行分組。

SELECT ending_at_year, MAX(mean_temp) max_temp, COUNT(DISTINCT year) c 
FROM 
(
SELECT mean_temp, year-i ending_at_year, year 
FROM [publicdata:samples.gsod] a 
CROSS JOIN 
    (SELECT i FROM [fh-bigquery:public_dump.numbers_255] WHERE i<3) b 
WHERE station_number=722860 
) 
GROUP BY ending_at_year 
HAVING c=3 
ORDER BY ending_at_year; 
+0

謝謝!我想知道你的計劃是什麼:)./ –

+0

你的意思是我在做什麼? –

+0

我GOOGLE了你的名字,他們說你是一個高手孩子:) –

2

我有另一種方式來做你正在努力實現的事情。見下面

SELECT word, max(words) 
FROM 
    (SELECT word, 
    word_count AS words 
    FROM [publicdata:samples.shakespeare] 
    WHERE corpus = 'macbeth'), 
    (SELECT word, 
    LEAD(word_count, 1) OVER (ORDER BY word) AS words 
    FROM [publicdata:samples.shakespeare] 
    WHERE corpus = 'macbeth'), 
    (SELECT word, 
    LEAD(word_count, 2) OVER (ORDER BY word) AS words 
    FROM [publicdata:samples.shakespeare] 
    WHERE corpus = 'macbeth') 
group by word order by word 

查詢,您可以嘗試和比較你的方法的性能(我沒有嘗試)

+1

有趣的 - 我沒有想到這種方法。它仍然是O(n)子查詢,但至少它們不是嵌套的,所以這可能會更好。不幸的是,我最好喜歡從另一個子查詢中獲取數據,而不是直接從表中獲取數據,我不認爲BigQuery會讓我緩存該子查詢,而不是將其轉儲到表中並使用它。但如果表現是一個問題,我可以改變這一點。 –