Возврат результатов скрипта BigQuery клиенту Python - PullRequest
0 голосов
/ 19 января 2020

Начиная с осени 2019 года, BigQuery поддерживает скриптинг , что отлично. Я не могу понять, способен ли Python клиент для BigQuery использовать эту новую функциональность.

Например, запустив следующий код Python:

client = bigquery.Client()
QUERY = """
BEGIN
    CREATE OR REPLACE TEMP TABLE t0 AS
        SELECT * FROM my_dataset.my_table WHERE foo < 1;

    SELECT SUM(bar) AS bar_sum FROM t0;

    DROP TABLE IF EXISTS t0;
END;
"""

query_job = client.query(QUERY)
rows = query_job.result()

... возвращает объект google.cloud.bigquery.table._EmptyRowIterator, хотя я вижу, что операторы в скрипте SQL успешно выполняются из веб-интерфейса BigQuery.

Как вернуть результаты из оператора SELECT в этом стандартном скрипте SQL клиенту Python?

1 Ответ

1 голос
/ 19 января 2020

Поддерживается, но вам необходимо принять во внимание следующую часть документации :

Сценарии выполняются в BigQuery с использованием jobs.insert, как и любой другой запрос, со сценарием с несколькими утверждениями, указанным в качестве текста запроса. При выполнении сценария для каждого оператора в сценарии создаются дополнительные задания, известные как дочерние задания , . Вы можете перечислить дочерние задания скрипта, вызвав jobs.list, передав идентификатор задания скрипта в качестве параметра parentJobId.

Когда в скрипте вызывается jobs.getQueryResults, он возвращает Результаты запроса для последнего оператора SELECT, DML или DDL для выполнения в сценарии, без результатов запроса, если ни один из приведенных выше операторов не был выполнен. Чтобы получить результаты всех операторов в сценарии, перечислите дочерние задания и вызовите jobs.getQueryResults для каждого из них.

В качестве примера я изменил ваш сценарий для запроса к публикуемой таблице c : bigquery-public-data.london_bicycles.cycle_stations. Это запускает три дочерних задания:

enter image description here

, где последний удаляет таблицу, а не возвращает ни одной строки :

enter image description here

Поэтому, если я запускаю файл Python, я получаю что-то вроде <google.cloud.bigquery.table._EmptyRowIterator object at 0x7f440aa33c88>.

Мы хотим получить результат вывода среднего запроса :

enter image description here

Быстрый тест закомментируйте оператор DROP и затем выполните итерации по строкам, чтобы получить результат sum=6676. Итак, что если мы хотим получить промежуточные результаты? Ответ, как и в ранее цитируемых документах, заключается в том, чтобы вызвать jobs.list и передать идентификатор задания сценария в качестве параметра parentJobId для получения идентификаторов дочерних заданий:

for job in client.list_jobs(parent_job=query_job.job_id):
    print("Job ID: {}, Statement Type: {}".format(job.job_id, job.statement_type))

Мы используем метод list_jobs и проверяем ID и тип оператора :

Job ID: script_job_80e...296_2, Statement Type: DROP_TABLE
Job ID: script_job_9a0...7fd_1, Statement Type: SELECT
Job ID: script_job_113...e13_0, Statement Type: CREATE_TABLE_AS_SELECT

Обратите внимание, что суффикс (0, 1, 2) указывает порядок выполнения но мы можем добавить двойную проверку, чтобы убедиться, что задание действительно является оператором SELECT, прежде чем получать результаты:

from google.cloud import bigquery

client = bigquery.Client()
QUERY = """
BEGIN
    CREATE OR REPLACE TEMP TABLE t0 AS
        SELECT name, bikes_count FROM `bigquery-public-data.london_bicycles.cycle_stations` WHERE bikes_count > 10;

    SELECT SUM(bikes_count) AS total_bikes FROM t0;

    DROP TABLE IF EXISTS t0;
END;
"""

query_job = client.query(QUERY)
query_job.result()

for job in client.list_jobs(parent_job=query_job.job_id):  # list all child jobs
    # print("Job ID: {}, Statement Type: {}".format(job.job_id, job.statement_type))
    if job.statement_type == "SELECT":  # print the desired job output only
        rows = job.result()
        for row in rows:
            print("sum={}".format(row["total_bikes"]))

output:

sum=6676
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...