2016-07-28 18 views
1

--- --- ZusammenfassungBigQuery - Wie erstellt man eine neue Spalte, in der die Berechnung die neue Spalte selbst enthält?

Ich habe drei Säulen: [visitorID], [Rang], [Zahlen].

In BigQuery, Ich möchte eine neue Spalte [Berechnung] erstellen, die einen Teil der Summe von [Zahlen] und [Berechnung] selbst, incluing angegebenen Bedingungen.

Das Problem, dem ich jetzt begegne, ist, dass "ich in BigQuery keine Spalte erstellen kann, die die Berechnung einschließlich der Spalte benötigt, die ich erstelle". Ich bin nicht sicher, ob mein Konzept oder Idee geeignet ist oder nicht, und ich hoffe, es gibt einige bessere Vorschläge.

--- Details ---

* Die Tabelle I haben:

Eine Tabelle mit drei Spalten: [visitorID], [Rang], [Zahlen].

* Die neue Spalte Ich brauche zu erstellen:

Sie möchten die Spalte [Berechnung] erstellen.

* Die Definition der Berechnung:

Nach der Bestellung von [visitorID] und [Rang], die [Berechnung] ist

(i) Wenn [numbers] = 0, dann [Berechnung ] = 0 (ii) Wenn [Zahlen] <> 0, DANN summieren Sie den aktuellen [Zahlen] -Wert und die vorherige [Berechnungs] -Nummer. (iii) Basierend auf (ii), wenn die Summe größer als 30 ist, dann [Berechnung] = 0, bleibt ELSE [Berechnung] derselbe Summenwert.

Siehe Beispiel wie folgt. enter image description here

* Das Problem I

Ich brauche bin Begegnung mit BigQuery zu verwenden, um diese Art der Berechnung zu tun. Was ich jedoch herausgefunden habe, ist die "Fenster-Summen-Funktion", die dafür keine gute Lösung war. Ich denke, der entscheidende Punkt ist, dass "In BigQuery kann ich keine Spalte erstellen, die die Berechnung einschließlich der Spalte benötigt, die ich erstelle".

Siehe Beispiel wie folgt. Tried window function, which was failed.

Das heißt, ich brauche immer den vorhandenen Wert, um eine neue Spalte zu erstellen. Ich habe meine Beispielabfrage wie folgt, die das Problem nicht lösen kann. Und Sie können auch den Druckbildschirm sehen, um zu verstehen, was das Problem ist.

Siehe Beispielabfrage wie folgt.

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 

* Sucht Vorschläge

Ich mag würde für Anregungen fragen. (1) In BigQuery, ist dieses Problem lösbar oder nicht? (2) Welche Methode oder Konzept fehlt mir? (3) Was ist ein besserer Weg, um das Problem in BigQuery zu lösen?

Vielen Dank.

Antwort

1

Für BigQuery die einzige Lösung, die ich bisher vorschlagen kann, ist, wie unten
Es genau yo produziert ergeben sich für den Preis erwarten Sie ein wenig über BigQuery User-Defined Functions zu lernen. Sehr leistungsfähiges Feature, wenn es richtig zu verwenden ist. In einigen Fällen hat es Speicherprobleme, die in Kürze behoben werden müssen, per this link.
Ich empfehle dringend, diese Funktion zu übernehmen!

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

Hallo Mikhail, Ich versuche, Ihre Methode, die unglaublich erfolgreich ist. Ich danke dir sehr. Und ich fand es eine Verbindung http://storage.googleapis.com/bigquery-udf-test-tool/testtool.html, wo man die UDF testen kann (aber noch nicht einen Debugger finden ... es ist schwierig, die UDF zu debuggen). Trotzdem, vielen Dank für Ihre Hilfe. Ich verstehe immer noch die Logik, die Sie verwendet haben (vor allem warum die GROUP_COONCAT verwenden), und ich fand, ohne die GROUP_CONCAT verwenden, wird die Länge in der For-Schleife Teil ein Problem sein. Habe gerade eine fantastische Lektion gelernt :-) –

0

Was Sie versuchen, ist innerhalb einer SQL Select-Anweisung nicht möglich. Sie fragen nach etwas, das inhärent Variablen, Schleifen und if-Anweisungen benötigt, die Ihnen in einer SQL Select-Anweisung nicht zur Verfügung stehen.

Zugegeben, Sie können diese Art von Sache in SQL-Code mit Tabellenwertfunktionen und gespeicherten Prozeduren .. Mit einer externen Programmiersprache, die für genau das, was Sie tun möchten, gebaut wird wahrscheinlich die einfachste Route für Sie sein .

Führen Sie die Abfrage nach [visitorID], [Rang], [numbers] innerhalb von SQL, und dann entwickeln Sie einfach die [Berechnung] Daten, wie Sie Ausgang in eine beliebige Datei oder einen Bildschirm, den Sie benötigen.

Hoffe, dass es Ihre Situation verdeutlicht.

Verwandte Themen