SQL - 不等左加入 BigQuery

Posted

技术标签:

【中文标题】SQL - 不等左加入 BigQuery【英文标题】:SQL - Unequal left join BigQuery 【发布时间】:2017-09-22 18:02:52 【问题描述】:

这里是新的。我正试图随着时间的推移获得每日和每周活跃用户。他们有 30 天的时间被视为不活跃。我的目标是创建可以按 user_id 拆分的图表,以显示群组、区域、类别等。

我创建了一个日期表来获取该时间段的每一天,并且我有一个简化的订单表,其中包含我需要计算它的基本信息。

我正在尝试使用以下 SQL 查询进行左连接以按日期获取状态:

WITH daily_use AS (
        SELECT
          __key__.id AS user_id
          , DATE_TRUNC(date(placeOrderDate), day) AS activity_date
        FROM `analysis.Order`
        where isBuyingGroupOrder = TRUE 
          AND testOrder = FALSE
        GROUP BY 1, 2
 ),
dates AS (
        SELECT DATE_ADD(DATE "2016-01-01", INTERVAL d.d DAY) AS date
        FROM
          (
           SELECT ROW_NUMBER() OVER(ORDER BY __key__.id) -1 AS d
           FROM `analysis.Order`
           ORDER BY __key__.id
           LIMIT 1096
          ) AS  d
        ORDER BY 1 DESC
      )

SELECT
      daily_use.user_id
    , wd.date AS date
    , MIN(DATE_DIFF(wd.date, daily_use.activity_date, DAY)) AS days_since_last_action
FROM dates AS wd

LEFT JOIN daily_use
    ON wd.date >= daily_use.activity_date
    AND wd.date < DATE_ADD(daily_use.activity_date, INTERVAL 30 DAY)

GROUP BY 1,2

我收到此错误:如果没有连接两侧的字段相等的条件,则无法使用 LEFT OUTER JOIN。在 BigQuery 中,我想知道如何解决这个问题。我在 BigQuery 中使用标准 SQL。

谢谢

【问题讨论】:

可能重复:***.com/questions/43858433/… BigQuery 将尝试让您使用相等条件,因为这对于大型表来说是不可扩展的(在随机播放数据时没有可使用的通用键)。如果您使用带有 WHERE 子句的 CROSS JOIN 会发生什么? 【参考方案1】:

以下是 BigQuery 标准 SQL,主要是在您的查询中重现逻辑,但不包括根本没有发现任何活动的日期

#standardSQL
SELECT
    daily_use.user_id
  , wd.date AS DATE
  , MIN(DATE_DIFF(wd.date, daily_use.activity_date, DAY)) AS days_since_last_action
FROM dates AS wd
CROSS JOIN daily_use
WHERE wd.date BETWEEN 
  daily_use.activity_date AND DATE_ADD(daily_use.activity_date, INTERVAL 30 DAY)
GROUP BY 1,2
-- ORDER BY 1,2

如果出于某种原因您仍然需要exactly 重现您的逻辑 - 您可以在上面使用最终的左连接,如下所示:

#standardSQL
SELECT *
FROM dates AS wd
LEFT JOIN (
  SELECT
    daily_use.user_id
    , wd.date AS date
    , MIN(DATE_DIFF(wd.date, daily_use.activity_date, DAY)) AS days_since_last_action
  FROM dates AS wd
  CROSS JOIN daily_use
  WHERE wd.date BETWEEN 
    daily_use.activity_date AND DATE_ADD(daily_use.activity_date, INTERVAL 30 DAY)
  GROUP BY 1,2
) AS daily_use
USING (date)
-- ORDER BY 1,2

【讨论】:

嘿 Mikhail Berlyant,这完美地回答了我的问题。您的第一个建议非常有效。我不需要填写没有数据的日期。范围内的日期和订单之间的天数是我们正在寻找的。非常感谢。 这是一个绝妙而有创意的解决方案,但是在我的情况下,我必须检查另一个表中的 10 亿行和 30 万行是否地理接近。 BigQuery 无法使用此“CROSS JOIN”解决方法来执行此操作。还有其他想法吗?...提前致谢。 请将您的问题作为新问题发布并提供所有需要的详细信息,我们将很乐意回答:o)

以上是关于SQL - 不等左加入 BigQuery的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery 中的多个左连接

SQL左连接避免空条目

左加入为新列?

SQL优化的方式

加入同一个表时 SQL 结果计数发生变化

内连接,外链接(左连接右连接全连接),交叉连接大总结+附SQL JOINS图解[转]