2014-07-24 59 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会让我缓存该子查询,而不是将其转储到表中并使用它。但如果表现是一个问题,我可以改变这一点。 –