Невозможно выполнить запрос к таблице без фильтра, который можно использовать для исключения раздела - PullRequest
0 голосов
/ 05 июля 2018

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

MERGE `wr_live.p_email_event`  t
using `wr_live.email_event` s
on t.user_id=s.user_id and t.event=s.event and t.timestamp=s.timestamp
WHEN NOT MATCHED THEN
INSERT (user_id,event,engagement_score,dest_email_domain,timestamp,tags,meta)
values (user_id,event,engagement_score,dest_email_domain,timestamp,tags,meta)

Я получаю

Невозможно выполнить запрос к таблице 'wr_live.p_email_event' без фильтра, который можно использовать для удаления разделов.

Какой правильный синтаксис? Также есть способ, которым я могу выразить короче вставки? без именования всех столбцов?

1 Ответ

0 голосов
/ 05 июля 2018

Какой правильный синтаксис?

Как видно из сообщения об ошибке - ваша секционированная таблица wr_live.p_email_event была создана с require partition filter, установленным в значение true. Это означает, что любой запрос к этой таблице должен иметь некоторый фильтр в соответствующем секционированном поле

Предполагая, что timestamp является этим разделенным полем - вы можете сделать что-то вроде ниже

MERGE `wr_live.p_email_event`  t
USING `wr_live.email_event` s
ON t.user_id=s.user_id AND t.event=s.event AND t.timestamp=s.timestamp
AND DATE(t.timestamp) > CURRENT_DATE()  -- this is the filter you should tune 
WHEN NOT MATCHED THEN
INSERT (user_id,event,engagement_score,dest_email_domain,timestamp,tags,meta)
VALUES (user_id,event,engagement_score,dest_email_domain,timestamp,tags,meta)   

Так что вам нужно сделать нижнюю строку такой, чтобы в действительности она не отфильтровывала все, что вам нужно для участия

AND DATE(t.timestamp) <> CURRENT_DATE()  -- this is the filter you should tune 

Например, я обнаружил, установив его на отметку времени в будущем - во многих случаях решает проблему, например

AND DATE(t.timestamp) > DATE_ADD(CURRENT_DATE(), INTERVAL 1 DAY)   

Конечно, если ваша таблица wr_live.email_event также разделена с require partition filter, установленным в true - вам нужно добавить тот же фильтр для s.timestamp

Также есть способ, которым я могу выразить короче вставку? без именования всех столбцов?

Для INSERT BigQuery DML требуется column names to be specified - нет способа (по крайней мере, мне это известно) избежать его с помощью оператора INSERT
Между тем, вы можете избежать этого, используя CREATE TABLE DDL из результата запроса. Это не потребует перечисления столбцов

Например, что-то вроде ниже

CREATE OR REPLACE TABLE `wr_live.p_email_event`
PARTITION BY DATE(timestamp) AS
SELECT * FROM `wr_live.p_email_event` 
WHERE DATE(timestamp) <> DATE_ADD(CURRENT_DATE(), INTERVAL 1 DAY)
UNION ALL 
SELECT * FROM `wr_live.email_event` s
WHERE NOT EXISTS (
  SELECT 1 FROM `wr_live.p_email_event` t
  WHERE t.user_id=s.user_id AND t.event=s.event AND t.timestamp=s.timestamp
  AND DATE(t.timestamp) > DATE_ADD(CURRENT_DATE(), INTERVAL 1 DAY)
)

Возможно, вы также захотите включить список опций таблицы через OPTIONS () - но похоже, что атрибут фильтра еще не поддерживается - поэтому, если он у вас есть / нужен - выше, этот атрибут «сотрет»: o (

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