如果没有可用于分区消除的过滤器,则无法查询表

Pen*_*m10 6 google-bigquery

我有一个分区表,很想使用 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)
Run Code Online (Sandbox Code Playgroud)

我得到

如果没有可用于分区消除的过滤器,则无法查询表“wr_live.p_email_event”。

什么是正确的语法?还有一种方法可以表达更短的插入内容吗?不命名所有列?

Mik*_*ant 7

什么是正确的语法?

正如您从错误消息中看到的那样 - 您的分区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)   
Run Code Online (Sandbox Code Playgroud)

因此,您需要在以下行中进行设置,以便它实际上不会过滤掉您需要参与的任何内容

AND DATE(t.timestamp) <> CURRENT_DATE()  -- this is the filter you should tune 
Run Code Online (Sandbox Code Playgroud)

例如,我发现,将来将其设置为时间戳 - 在许多情况下可以解决该问题,例如

AND DATE(t.timestamp) > DATE_ADD(CURRENT_DATE(), INTERVAL 1 DAY)   
Run Code Online (Sandbox Code Playgroud)

当然,如果您的wr_live.email_event表也​​分区require partition filter设置为 true - 您需要为 s.timestamp 添加相同的过滤器

还有一种方法可以表达更短的插入内容吗?不命名所有列?

BigQuery DML 的 INSERT 要求column names to be specified- 没有办法(至少我知道)使用 INSERT 语句避免它
同时,您可以通过使用 DDL 的 CREATE TABLE 从查询结果中避免这种情况。这不需要列出列

例如,像下面这样

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)
)
Run Code Online (Sandbox Code Playgroud)

您可能还想通过 OPTIONS() 包含表选项列表 - 但看起来过滤器属性不受支持 - 所以如果你有/需要它 - 上面将“擦除”这个属性:o(