Разделенные таблицы BigQuery: какой самый короткий способ указать месяц? - PullRequest
0 голосов
/ 22 мая 2018

Хотите знать, какой самый короткий способ указать месяц при запросе секционированных таблиц.

TIMESTAMP_TRUNC для месяца выглядит заманчиво, но, похоже, не работает как фильтр секционирования:

SELECT SUM(views) views
FROM `fh-bigquery.wikipedia_v2.pageviews_2018`
WHERE TIMESTAMP_TRUNC(datehour, month) = '2018-04-01'

Cannot query over table 'fh-bigquery.wikipedia_v2.pageviews_2018' without a filter that can be used for partition elimination

BETWEEN даты тоже выглядят заманчиво, но для этого нужно знать, сколько дней в каждом месяце:

SELECT SUM(views) views
FROM `fh-bigquery.wikipedia_v2.pageviews_2018`
WHERE DATE(datehour) BETWEEN '2018-04-01' AND '2018-04-31'

Could not cast literal "2018-04-31" to type DATE at [3:47]

DATE_SUB(DATE_ADD(month), day работает, но для этого нужно дважды набрать дату и ввести слишком долго:

SELECT SUM(views) views
FROM `fh-bigquery.wikipedia_v2.pageviews_2018`
WHERE DATE(datehour) 
  BETWEEN '2018-04-01' 
  AND DATE_SUB(DATE_ADD('2018-04-01', INTERVAL 1 MONTH), INTERVAL 1 DAY) 

15746003449

Как бы вы улучшили это?

Ответы [ 2 ]

0 голосов
/ 22 мая 2018

Я бы просто сделал:

SELECT SUM(views) as views
FROM `fh-bigquery.wikipedia_v2.pageviews_2018`
WHERE hour >= date '2018-04-01' AND hour < date '2018-05-01';

Вы можете поместить константы даты в CTE:

with params as (
      select date '2018-04-01' as dte
     )
select sum(views) as views
from params cross join
     `fh-bigquery.wikipedia_v2.pageviews_2018`
where hour >= params.dte AND hour < date_add(params.dte, interval 1 month)
0 голосов
/ 22 мая 2018

Обновление : во время дальнейших экспериментов это мое лучшее решение:

SELECT SUM(views) views
FROM `fh-bigquery.wikipedia_v2.pageviews_2018`
WHERE DATE_TRUNC(DATE(datehour), month) = '2018-04-01'

По сути, это первая попытка в вопросе, плюс приведение метки времени к DATE, а затем применение DATE_TRUNC.

Оставляя другие опции, которые я попробовал ниже, так как они могут быть полезны для других ситуаций.


Один вариант - использовать WITH для определения переменной, таким образом набирая месяцтолько один раз:

WITH month AS (SELECT DATE('2018-04-01') m), 
  full_month AS (SELECT m AS s, DATE_SUB(DATE_ADD(m, INTERVAL 1 MONTH), INTERVAL 1 DAY) AS e FROM month)

SELECT SUM(views) views
FROM `fh-bigquery.wikipedia_v2.pageviews_2018`
WHERE DATE(datehour) 
  BETWEEN (SELECT s FROM full_month) AND (SELECT e FROM full_month)

Аналогично, вы можете определить функции SQL UDF:

CREATE TEMPORARY FUNCTION month() AS (DATE('2018-04-01'));
CREATE TEMPORARY FUNCTION month_end() AS (DATE_SUB(DATE_ADD(month(), INTERVAL 1 MONTH), INTERVAL 1 DAY));

SELECT SUM(views) views
FROM `fh-bigquery.wikipedia_v2.pageviews_2018`
WHERE DATE(datehour) BETWEEN month() AND month_end() 

Для обоих вариантов BigQuery может идентифицировать и оптимизировать сканирование только необходимых разделов.

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