代码之家  ›  专栏  ›  技术社区  ›  Pentium10

如果没有可用于分区消除的筛选器,则无法对表进行查询

  •  1
  • Pentium10  · 技术社区  · 6 年前

    我有一个分区表,很想使用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 回复  |  直到 6 年前
        1
  •  2
  •   Mikhail Berlyant    6 年前

    正确的语法是什么?

    从错误消息中可以看到-您的分区 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 
    

    例如,我发现,在将来将其设置为timestamp-在许多情况下会解决这个问题,比如

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

    当然,如果你 wr_live.email_event 表也用 需要分区筛选器 设置为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(