BigQuery - 使用子查询和 OR 语句连接多个条件

Posted

技术标签:

【中文标题】BigQuery - 使用子查询和 OR 语句连接多个条件【英文标题】:BigQuery - Joining on multiple conditions using subqueries and OR statements 【发布时间】:2017-05-08 22:51:44 【问题描述】:

是否有在多个潜在条件下连接两个表?

我目前正在将一些代码从 Postgres 迁移到 Bigquery,在那里我加入了多个潜在值,例如:

SELECT
 *
FROM
 (
 SELECT
   offer_table.offer_id
   ,customer_table.customer_name
   ,customer_table.visit_count
   ,ROW_NUMBER() OVER (PARTITION BY offer_table.offer_id ORDER BY customer_table.visit_count DESC) AS customer_visit_rank
 FROM
   offer_table
   LEFT JOIN customer_table ON
    (
    offer_table.customer_id = customer_table.customer_id
    OR offer_table.email = customer_table.email
    OR offer_table.phone = customer_table.phone
    )
 ) dummy
WHERE
  customer_visit_rank = 1

我需要这样做,因为我的报价和客户数据对我们的 ID、电子邮件和电话字段的使用不一致,但都是有效的潜在匹配项。如果多个字段有效(例如:id 和电子邮件匹配),会有重复的行,我会在使用 ORDER BY 部分排名后根据 row_number 列将它们过滤掉。

但是,当我尝试在 BigQuery 中加入多个条件时,我收到以下错误消息:

LEFT OUTER JOIN cannot be used without a condition that is an equality of fields from both sides of the join.

有没有人想出一个解决方案来加入多个值而不是执行上述操作?

【问题讨论】:

您能否对三个JOIN ON 条件中的每一个运行三个单独的查询,然后使用UNIONUNION ALL 组合结果?支持UNION ALL,因为它只会追加找到的行,而不必像UNION 那样对删除重复项进行排序。所以基本上SELECT ... ON customer_id ... UNION ALL SELECT ... ON email ... UNION ALL SELECT ... ON phone。如果这是正确的,我可以回答一下吗? 使用标准 SQL。 @flutter 这样做不会让每个 offer_id 有重复的行吗?我正在尝试在具有正确数据的 customer_table 行上为每个 offer_id 匹配一个唯一行(在此示例中为最高 visit_count)。 只需像 Gordon 建议的那样使用标准 SQL。 cloud.google.com/bigquery/docs/reference/standard-sql 在链接的Standard SQL 语法中我可以看到UNION DISTINCT。你试过吗? 【参考方案1】:

您可以编写单独的查询,然后使用COALESCE

SELECT
  *
FROM
  (
    SELECT
      offer_table.offer_id
      ,COALESCE(c1.customer_name,c2.customer_name,c3.customer_name)
      ,COALESCE(c1.visit_count,c2.visit_count,c3.visit_count)
      ,ROW_NUMBER() OVER (PARTITION BY offer_table.offer_id ORDER BY customer_table.visit_count DESC) AS customer_visit_rank
    FROM
      offer_table
    LEFT JOIN customer_table c1
      ON offer_table.customer_id = customer_table.customer_id
    LEFT JOIN customer_table c2
      ON offer_table.email = customer_table.email
    LEFT JOIN customer_table c3
      ON offer_table.phone = customer_table.phone
   )
 ) AS dummy
WHERE
  customer_visit_rank = 1

【讨论】:

我在其他一些示例用例上尝试过这种方法,这很容易导致Resources exceeded during query execution: The query could not be executed in the allotted memory. Peak usage: 103% of limit. Top memory consumer(s): aggregate functions and GROUP BY clauses: 100%

以上是关于BigQuery - 使用子查询和 OR 语句连接多个条件的主要内容,如果未能解决你的问题,请参考以下文章

BIGQUERY:连接谓词中的表不受支持的子查询

BigQuery 避免多个子查询

BigQuery:需要在相关子查询中返回记录类型的唯一值

带有case语句的bigquery中的子选择

BigQuery:从表连接引起的子选择中删除记录

使用连接语句和子查询准备 CakePHP 查询