2016-07-28 4 views
1

---概要---BigQuery - 計算に新しい列自体が含まれる新しい列を作成するにはどうすればよいですか?

[visitorID]、[rank]、[numbers]の3つの列があります。

BigQueryで 指定した条件を含む[数値]と[計算]の合計の一部である という新しい列[計算]を作成します。

私が今直面する問題は、「BigQueryでは、作成中の列を含めて計算が必要な列を作成できません」ということです。 私のコンセプトやアイデアが適切かどうかはわかりませんが、 と私はいくつか良い提案があることを願っています。

---詳細---

*私が持っている表:3列の

テーブル:[visitorID]、[ランク]、[番号]。

*私が作成する必要が新しいカラム:

をコラム[計算]を作成する必要があります。

*計算の定義:[visitorID]によって、および[ランク]注文後

、 [計算]は

である(I)[番号] = 0の場合、THEN [計算] = 0 (ii)[numbers] <が0の場合、THENは現在の[数値]と前の[計算]の数値を合計します。 (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の問題を解決するにはどうすればよいですか?

ありがとうございました。 BigQueryのために

答えて

1

それはまさにあなたが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]、[ランク]、[番号]のためのクエリを実行し、ちょうどあなたがする必要がどのようなファイルや画面にあなたの出力として、[計算]データを開発します。

あなたの状況を明確にすることを願っています。

関連する問題