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

时间:2018-07-05 14:39:23

标签: 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)

我知道

  

在没有过滤器的情况下无法查询表“ wr_live.p_email_event”   可用于消除分区。

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

1 个答案:

答案 0 :(得分:2)

  

正确的语法是什么?

从错误消息中可以看到-创建的分区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添加相同的过滤器

  

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

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)
)

您可能还希望通过OPTIONS()包含表选项列表-但看起来还不支持filter属性-因此,如果确实有/需要它,则上面将“擦除”此属性:o(