【问题标题】:Is there a way to do LEFT JOIN LATERAL with BigQuery?有没有办法用 BigQuery 做 LEFT JOIN LATERAL?
【发布时间】:2020-03-30 04:50:37
【问题描述】:

鉴于某些行具有重复的names 和不同的timestamps,我想选择具有最新timestamp 的行,如果重复的name 出现在第一个@ 的45 分钟内987654328@.

这是在 PostgreSQL 中起作用的:

SELECT i.ts AS base_timestamp, j.ts AS newer_timestamp, i.name
FROM tbl i
LEFT JOIN LATERAL
(SELECT j.ts
 FROM tbl j
 WHERE i.name = j.name
 AND j.ts > i.ts
 AND j.ts < (i.ts + INTERVAL '45 minutes')
) j ON TRUE
WHERE j.ts is NULL

LATERAL 的精彩解释在这里: https://heap.io/blog/engineering/postgresqls-powerful-new-join-type-lateral

LATERAL join 类似于 SQL foreach 循环,其中 PostgreSQL 将遍历结果集中的每一行并使用该行作为参数评估子查询。

所以它就像一个相关的子查询,但在连接中。

然后我只取没有更新时间戳 (WHERE j.ts is NULL) 的行。

如何在 BigQuery 中执行此操作?

编辑:我已按照 cmets 的要求创建了 an example of the PostgreSQL grouping on SQLFiddle

输入:

  ('Duplication Example','2019-06-22 19:10:25'),
  ('Duplication Example','2019-06-22 23:58:31'), 
  ('Duplication Example','2019-06-23 00:08:00')

输出(中间行已删除时间戳 23:58:31):

base_timestamp          newer_timestamp name
2019-06-22T19:10:25Z    (null)          Duplication Example
2019-06-23T00:08:00Z    (null)          Duplication Example

【问题讨论】:

  • 这里有一些巧妙之处在于将秒用作数字 RANGE 子句 medium.com/@ubethke/…
  • 请澄清-您是否对解决/解决帖子标题中的内容(这是非常通用和概念性的)或问题正文中第一句中的内容更感兴趣(更多实用且最有可能解决您的实际用例)?这是两个非常不同的东西 - 所以请澄清!
  • 嗨@MikhailBerlyant,感谢您查看我的问题。我对解决问题主体第一句中所述的具体问题更感兴趣。如果答案以“不,BigQuery 没有 LATERAL,您需要使用 ... 来解决您的问题”开头,这将是最有用的。
  • 这正是我所期望的——一旦有空,我会尽快回复你:o)
  • 请添加一些输入数据和预期输出的简化示例。我试图阅读/分析您的案例,发现仍然不清楚您想要应用什么逻辑来产生结果。输入/输出的好例子肯定会有所帮助。一个名字就足够了,但请提供一些具有代表性的 ts(时间戳)

标签: google-bigquery lateral-join


【解决方案1】:

您的案例看起来有点像窗口函数的任务。但是,由于您似乎对横向连接比对解决您提出的问题更感兴趣: 在 BigQuery 中,afaik 只有一个隐式版本的横向连接:当使用非嵌套数组连接时。

这展示了这个想法:

WITH t AS (
  SELECT 'a' as id, [2,3] as arr 
  UNION ALL SELECT 'b', [56, 7]
)

SELECT * EXCEPT(arr) 
FROM t LEFT JOIN UNNEST(arr)

【讨论】:

  • 马丁兄弟你好!我同意,这看起来确实像一个可以通过窗口函数完成的任务。大约在您提交答案的同时,我添加了一条链接到这篇文章的评论:medium.com/@ubethke/… ...但我仍然不清楚具体该怎么做。您的答案似乎更像是 CROSS JOIN 替代品:WITH t AS ( SELECT 'a' as id, [2,3] AS arr UNION ALL SELECT 'b', [56, 7] AS arr ) SELECT id, arr FROM t CROSS JOIN t.arr
  • 不知道你的意思,但未嵌套数组上的交叉连接也是隐式横向连接。
  • 更清楚一点:如果您认为这需要 BigQuery 中的窗口函数,请显示带有窗口函数的查询。我有兴趣解决问题中所述的问题,但我不知道如何使用您提供的查询示例来解决问题。
  • 如帖子中所述,我没有解决您的问题,而是解释了 BigQuery 中的横向连接。一切都好。
【解决方案2】:

这可以使用 WINDOW 功能存档。

SELECT
  name,
  MAX(timestamp) AS timestamp_new
FROM
(
  SELECT 
    i.name,
    COUNT(*) OVER (PARTITION BY i.name ORDER BY i.ts RANGE BETWEEN 45 * 60 * 1000 PRECEDING AND CURRENT ROW) as 45_window_count,
    i.ts AS timestamp
  FROM 
    tbl i
)
WHERE 45_window_count > 1
GROUP BY user

【讨论】:

  • 这似乎需要对数字范围进行更正,因为 45,000,000 毫秒超过 12 小时。正确的计算更像是 45 * 60 * 1000,不是吗? 45 分钟 * 一分钟 60 秒 * 一秒 1000 毫秒。
  • 正确。更新了答案。
猜你喜欢
  • 2020-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-10
  • 1970-01-01
  • 2012-04-05
  • 1970-01-01
相关资源
最近更新 更多