2016-07-28 1 views
1

--- Резюме ---BigQuery - Как создать новый столбец, где вычисление включает в себя новый столбец?

У меня есть три колонки: [visitorID], [ранг], [числа].

В 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-loop будет проблемой. Просто выучил фантастический урок :-) –

0

То, что вы пытаетесь сделать, невозможно в инструкции SQL Select. Ваш запрос сделать что-то, что по своей сути потребует переменные, циклы и операторы if, ни один из которых не доступен вам в инструкции SQL Select.

Предоставлено, вы можете делать такие вещи внутри кода SQL, используя функции, связанные с таблицей, и хранимые процедуры. Использование внешнего языка программирования, который был построен именно для того, что вы хотите сделать, скорее всего будет самым простым путем для вас ,

Запустите запрос для [userID], [rank], [numbers] внутри SQL, а затем просто создайте данные [вычисления] при выводе на любой файл или экран, который вам нужен.

Надеюсь, он уточнит вашу ситуацию.

Смежные вопросы