2016-07-28 93 views
1

--- Summary --- ---BigQuery - 如何创建计算包含新列自身的新列?

我有三列:[visitorID],[rank],[数字]。

在BigQuery中, 我想创建一个新的列[计算], ,它是[数字]和[计算]本身的总和的一部分,包括指定的条件。

现在遇到的问题是“在BigQuery中,我无法创建需要计算的列,包括我创建的列”。 我不知道我的概念或想法是否合适, ,我希望有更好的建议。

--- ---详细

*表我:

一个表有三列:[visitorID],[等级],[数字]。

*新的列,我需要创建:

需要创建列[计算。

*计算的定义:

由[visitorID]和订购[秩], 的[计算之后是

(ⅰ)如果[号码] = 0,则[计算] = 0 (ii)如果[数字] <> 0,则将当前的[数字]值和前一个[计算]数字相加。 (iii)基于(ii),如果总和大于30,则[计算] = 0,ELSE [计算]保持相同的总和值。

请参阅下面的示例。 enter image description here

*我遇到

我需要使用的BigQuery做这样的计算问题。 但是,我想到的是“窗口总和函数”,这似乎不是一个很好的解决方案。 我认为关键的一点是“在BigQuery中,我无法创建需要计算的列,包括我正在创建的列”。

请参阅下面的示例。 Tried window function, which was failed.

也就是说,我总是需要存在的值来创建一个新列。 我有我的示例查询如下,这不能解决问题。 而且您还可以看到打印屏幕以了解问题所在。

请参阅下面的示例查询。

SELECT 
    visitorID, 
    rank, 
    numbers, 
    SUM(numbers) OVER (PARTITION BY visitorID ORDER BY rank) AS window_sum_current, 
    SUM(numbers) OVER (PARTITION BY visitorID ORDER BY rank ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS window_sum_prec1  
FROM sample_table 

*寻求建议

我想问的建议。 (1)在BigQuery中,这个问题是否可以解决? (2)我缺乏什么方法或概念? (3)什么是解决BigQuery问题的更好方法?

非常感谢。

回答

1

对于BigQuery我目前可以提出的唯一解决方案如下
它产生的结果是你期望的价格,你可以学到一些关于BigQuery User-Defined Functions。非常强大的功能,如果使用得当。在某些情况下,它有内存问题,很快将根据this link解决。
我强烈建议采用此功能!

SELECT visitorID, rank, numbers, calculation FROM JS(
// input table 
(SELECT visitorID, 
    GROUP_CONCAT(CONCAT(STRING(100000 + rank), ',', STRING(numbers)), ';') AS list 
    FROM 
    (SELECT 1001 AS visitorID, 1 AS rank, 0 AS numbers), 
    (SELECT 1001 AS visitorID, 2 AS rank, 13 AS numbers), 
    (SELECT 1001 AS visitorID, 3 AS rank, 13 AS numbers), 
    (SELECT 1001 AS visitorID, 4 AS rank, 6 AS numbers), 
    (SELECT 1001 AS visitorID, 5 AS rank, 4 AS numbers), 
    (SELECT 1001 AS visitorID, 6 AS rank, 5 AS numbers), 
    (SELECT 1001 AS visitorID, 7 AS rank, 26 AS numbers), 
    (SELECT 1001 AS visitorID, 8 AS rank, 32 AS numbers), 
    (SELECT 999 AS visitorID, 1 AS rank, 0 AS numbers), 
    (SELECT 999 AS visitorID, 2 AS rank, 2 AS numbers), 
    (SELECT 999 AS visitorID, 3 AS rank, 2 AS numbers), 
    (SELECT 999 AS visitorID, 4 AS rank, 2 AS numbers), 
    (SELECT 999 AS visitorID, 5 AS rank, 2 AS numbers), 
    (SELECT 999 AS visitorID, 6 AS rank, 24 AS numbers) 
    GROUP BY visitorID 
), 
// input columns 
visitorID, list, 
// output schema 
"[{name: 'visitorID', type: 'integer'}, 
{name: 'rank', type: 'integer'}, 
{name: 'numbers', type: 'integer'}, 
{name: 'calculation', type: 'integer'}]", 
// function 
"function(r, emit){ 
    var list = r.list.split(';'); 
    list.sort(); 
    calculation = 0; 
    for (var i = 0; i < list.length; i++) { 
    rank = parseInt(list[i].split(',')[0]) - 100000; 
    numbers = parseInt(list[i].split(',')[1]); 
    if (numbers !== 0) calculation += numbers; 
    if (calculation > 30) calculation = 0; 
    emit({visitorID: r.visitorID, rank: rank, 
      numbers: numbers, calculation: calculation}); 
    } 
}" 
) 
+0

嗨米哈伊尔,我正在尝试你的方法,这是令人难以置信的成功。非常感谢。我发现有一个链接http://storage.googleapis.com/bigquery-udf-test-tool/testtool.html,可以测试UDF(但仍然无法找到调试器......很难调试UDF )。尽管如此,非常感谢您的帮助。我仍然理解你正在使用的逻辑(尤其是为什么使用GROUP_COONCAT),并且我发现没有使用GROUP_CONCAT,for循环部分的长度将成为问题。刚刚学到了一个奇妙的教训:-) –

0

你正在尝试做的事情在SQL Select语句中是不可能的。你要求做一些本质上需要变量,循环和if语句的东西,而这些语句在SQL Select语句中都不可用。当然,您可以使用表值函数和存储过程在SQL代码中执行此类事情。使用为您想要执行的外部编程语言可能会成为您最简单的路线。

在SQL中对[visitorID],[rank],[numbers]运行查询,然后在输出到任何需要的文件或屏幕时开发[计算]数据。

希望能够澄清你的情况。