Google bigquery BigQuery中的自连接问题

Google bigquery BigQuery中的自连接问题,google-bigquery,Google Bigquery,我试图对当前行周围特定日期范围的值求和。由于Bigquery不支持windows函数中的日期范围,因此我使用自连接,如下所示: with test_data as ( select 1 val1, 7 val2, 'ord001' id, timestamp('2019-01-01 04:00:00') dt_order union all select 2 val1, 14 val2, 'ord002' id, timestamp('2019-01-02 05:00:00')

我试图对当前行周围特定日期范围的值求和。由于Bigquery不支持windows函数中的日期范围,因此我使用自连接,如下所示:

with test_data as (
   select 1 val1, 7 val2, 'ord001' id, timestamp('2019-01-01 04:00:00') dt_order
   union all
   select 2 val1, 14 val2, 'ord002' id, timestamp('2019-01-02 05:00:00') dt_order
   union all
   select 3 val1, 21 val2, 'ord003' id, timestamp('2019-01-03 06:00:00') dt_order
)

,revenue_coeff as (
select 
   td.id,
   td.val1 *
   (select sum(td1.val2) / sum(td1.val1)
    from test_data td1
    where td1.dt_order >= timestamp_sub(td.dt_order, interval 24 hour) and
       td1.dt_order < timestamp_add(td.dt_order, interval 6 minute)
    )
from test_data td
)

select * from revenue_coeff
这个玩具查询工作得很好。但是,当我试图使用一个真正的BigQuery表时,我得到了一条“如果没有一个条件,即连接两边的字段相等,则不能使用左外部连接”消息。
如何在BQ中实现这样的查询?提前谢谢

下面是BigQuery标准SQL

我会在你文章的末尾首先回答你的问题,但随后会在你文章的顶部发表你的声明。所以

我得到了一条“如果没有连接两边字段相等的条件,就不能使用左外连接”消息。如何在BQ中实现这样的查询

正如您所看到的-诀窍在于使用UNIX_SECONDS函数将时间戳数据类型转换为int


显然-我建议您使用第二个选项

您也可以执行左外连接,如:

select a.val1, a.id, 
   sum(if(b.dt_order >= timestamp_sub(a.dt_order, interval 24 hour) and b.dt_order <= timestamp_add(a.dt_order, interval 6 minute), b.val2, 0.0))
   /
   sum(if(b.dt_order >= timestamp_sub(a.dt_order, interval 24 hour) and b.dt_order <= timestamp_add(a.dt_order, interval 6 minute), b.val2, 0.0)) 
from test_data a
left join test_data b on 1=1
group by 1,2

但是,您必须管理上游的零除法错误,或者在其中添加case语句。

这样对其他人来说就很清楚了-左JOIN with ON TRUE只是说CROSS JOINYes的很长一段路。尽管有些人觉得它没有交叉连接那么冗长/混乱。同意。这可能是个人偏好的问题,而个人偏好又来自经验。所以,对我来说,这是完全相反的-在这种情况下使用交叉连接-看起来不那么冗长,也不那么混乱,因为它明确地表达了应该做什么,即交叉连接与使用左连接欺骗系统。。。真的然而,true上的左连接和交叉连接之间的区别在于,左连接实际上保留了左表-交叉连接没有。您的速率很低。重要提示-您可以使用投递答案左侧投票下方的勾号标记接受答案。看看为什么它很重要!同样重要的是对答案进行投票。投票选出有帮助的答案。。。当有人回答你的问题时,你可以检查一下该做什么。遵循这些简单的规则,你可以提高自己的声望得分,同时让我们有动力去回答你的问题:O请考虑!谢谢你详细的回答。对于这个问题,这确实是一个优雅的解决方案。仍然不能同意您对BQ中日期范围的支持,代码需要一些注释,这不是自解释的。
#standardSQL
WITH `project.dataset.test_data` AS (
   SELECT 1 val1,  7 val2, 'ord001' id, TIMESTAMP('2019-01-01 04:00:00') dt_order UNION ALL
   SELECT 1 val1, 14 val2, 'ord002' id, TIMESTAMP('2019-01-02 05:00:00') dt_order UNION ALL
   SELECT 1 val1, 21 val2, 'ord003' id, TIMESTAMP('2019-01-03 06:00:00') dt_order
), revenue_coeff AS (
  SELECT id, val1  * SUM(val2) OVER(win) / SUM(val1) OVER(win)
  FROM `project.dataset.test_data` td1
  WINDOW win AS (ORDER BY UNIX_SECONDS(dt_order) RANGE BETWEEN 86400 PRECEDING AND 359 FOLLOWING )
)
SELECT * FROM revenue_coeff   
select a.val1, a.id, 
   sum(if(b.dt_order >= timestamp_sub(a.dt_order, interval 24 hour) and b.dt_order <= timestamp_add(a.dt_order, interval 6 minute), b.val2, 0.0))
   /
   sum(if(b.dt_order >= timestamp_sub(a.dt_order, interval 24 hour) and b.dt_order <= timestamp_add(a.dt_order, interval 6 minute), b.val2, 0.0)) 
from test_data a
left join test_data b on 1=1
group by 1,2