2016-07-28 67 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]運行查詢,然後在輸出到任何需要的文件或屏幕時開發[計算]數據。

希望能夠澄清你的情況。