【问题标题】:BigQuery SQL running totalsBigQuery SQL 运行总计
【发布时间】:2013-01-17 20:15:56
【问题描述】:

知道如何在 BigQuery SQL 中计算运行总计吗?

id   value   running total
--   -----   -------------
1    1       1
2    2       3
3    4       7
4    7       14
5    9       23
6    12      35
7    13      48
8    16      64
9    22      86
10   42      128
11   57      185
12   58      243
13   59      302
14   60      362 

对于使用任一相关标量查询的传统 SQL 服务器来说都不是问题:

SELECT a.id, a.value, (SELECT SUM(b.value)
                       FROM RunTotalTestData b
                       WHERE b.id <= a.id)
FROM   RunTotalTestData a
ORDER BY a.id;

或加入:

SELECT a.id, a.value, SUM(b.Value)
FROM   RunTotalTestData a,
       RunTotalTestData b
WHERE b.id <= a.id
GROUP BY a.id, a.value
ORDER BY a.id;

但我找不到让它在 BigQuery 中工作的方法...

【问题讨论】:

    标签: google-bigquery


    【解决方案1】:

    问题在于第二个查询,BigQuery 将联合 FROM 表达式中的 2 个表。

    我不确定第一个,但可能 bigquery 不喜欢 Select 表达式中的子选择,只喜欢 FromExpression 中的子选择。所以你需要将子查询移动到 from 表达式中,并 JOIN 结果。

    另外,您可以尝试一下我们的 JDBC 驱动程序: Starschema BigQuery JDBC Driver

    只需将其加载到 Squirrel SQL 或 RazorSQL 或任何支持 JDBC 驱动程序的工具中,请确保通过设置打开查询转换器:

    transformQuery=true

    在属性或 JDBC url 中,每个信息都可以在项目页面中找到。完成此操作后,尝试运行第二个查询,它将转换为与 BigQuery 兼容的联接。

    【讨论】:

    • 你能举个 BigQuery 查询的例子吗?我看不到如何将子选择从 SELECT 移动到 FROM,因为它引用了 B?你不能加入
    • 感谢提示 - 但 BQ jdbc 驱动程序(和 SquirrelSQL)没有运气 - 总是出错(sqlState:null,errorCode:0)。
    • @AlenVrečko 如果您打开日志记录,并在调试级别设置,它也会注销已解析的查询。我们使我们的解析器与报告工具兼容,因为我们从 0 构建了一个 ANTLR 语法,它只接受 FROM 处的子查询。 Examples can be found here
    • @Sasa 这很糟糕,但是当我读到由于 WHERE 中的
    【解决方案2】:

    你可能已经想通了。但这里有一种方法,但不是最有效的方法:

    JOIN 只能使用相等比较来完成,即不能使用 b.id

    https://developers.google.com/bigquery/docs/query-reference#joins

    如果你问我,这很蹩脚。但是有一个解决方法。只需对某个虚拟值使用相等比较来获得笛卡尔积,然后将 WHERE 用于

    SELECT a.id, SUM(a.value) as rt 
    FROM RunTotalTestData a 
    JOIN RunTotalTestData b ON a.dummy = b.dummy 
    WHERE b.id <= a.id 
    GROUP BY a.id 
    ORDER BY rt
    

    您也可以手动限制时间:

    SELECT a.id, SUM(a.value) as rt 
    FROM (
        SELECT id, timestamp RunTotalTestData 
        WHERE timestamp >= foo 
        AND timestamp < bar
    ) AS a 
    JOIN (
        SELECT id, timestamp, value RunTotalTestData 
        WHERE timestamp >= foo AND timestamp < bar
    ) b ON a.dummy = b.dummy 
    WHERE b.id <= a.id 
    GROUP BY a.id 
    ORDER BY rt
    

    更新:

    您不需要特殊属性。你可以使用

    SELECT 1 AS one
    

    并加入其中。

    随着计费的进行,连接表在处理中计数。

    【讨论】:

    【解决方案3】:

    2018 年更新:原问题中的查询现在无需修改即可工作。

    #standardSQL
    WITH RunTotalTestData AS (
      SELECT * FROM UNNEST([STRUCT(1 AS id, 1 AS value),(2,0),(3,1),(4,1),(5,2),(6,3)]) 
    )
    
    SELECT a.id, a.value, (SELECT SUM(b.value)
                           FROM RunTotalTestData b
                           WHERE b.id <= a.id) runningTotal
    FROM   RunTotalTestData a
    ORDER BY a.id;
    

    2013 年更新:您可以使用 SUM() OVER() 来计算运行总计。

    在你的例子中:

    SELECT id, value, SUM(value) OVER(ORDER BY id)
    FROM [your.table]
    

    一个工作示例:

    SELECT word, word_count, SUM(word_count) OVER(ORDER BY word)
    FROM [publicdata:samples.shakespeare]
    WHERE corpus  = 'hamlet'
    AND word > 'a' LIMIT 30;
    

    【讨论】:

    • 这实际上在金融蒙特卡罗模拟中非常有用,我们需要累积小随机偏差的总和来模拟价格路径。
    • 此语法也适用于标准 SQL。请参阅有关分析函数的文档。 cloud.google.com/bigquery/docs/reference/standard-sql/…
    • 2018 年更新显示correlated subquery,这些在数据库中通常很糟糕。相关子查询实际上是在进行三角自连接;每一行都运行计算以对所有前面的行求和。我不了解 Bigquery 的内部结构,查询规划器完全有可能将其转换为其他东西,例如窗口函数sum() over(),它只需要一次传递数据,但如果不需要,那么在 2018 年更新中允许使用原始语法是一种倒退。
    猜你喜欢
    • 2015-08-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2023-04-10
    • 1970-01-01
    • 2022-10-14
    • 1970-01-01
    • 2015-04-02
    相关资源
    最近更新 更多