【问题标题】:Distinct Count across Bigquery arraysBigquery 数组中的不同计数
【发布时间】:2019-02-28 08:25:50
【问题描述】:

我想跨行连接数组,然后进行不同的计数。理想情况下,这会起作用:

WITH test AS
(
  SELECT
  DATE('2018-01-01') as date,
  2 as value,
  [1,2,3] as key
  UNION ALL
  SELECT
  DATE('2018-01-02') as date,
  3 as value,
  [1,4,5] as key
)
SELECT
  SUM(value) as total_value,
  ARRAY_LENGTH(ARRAY_CONCAT_AGG(DISTINCT key)) as unique_key_count
FROM test

很遗憾,ARRAY_CONCAT_AGG 函数不支持 DISTINCT 运算符。我可以取消嵌套数组,但随后我得到一个扇出并且值列的总和是错误的:

WITH test AS
(
  SELECT
  DATE('2018-01-01') as date,
  2 as value,
  [1,2,3] as key
  UNION ALL
  SELECT
  DATE('2018-01-02') as date,
  3 as value,
  [1,4,5] as key
)

SELECT
  SUM(value) as total_value,
  COUNT(DISTINCT k) as unique_key_count

FROM test
  CROSS JOIN UNNEST(key) k

有什么我遗漏的东西可以让我避免加入未嵌套的数组吗?

【问题讨论】:

    标签: arrays google-bigquery


    【解决方案1】:

    这里有一个替代方案:

    CREATE TEMP FUNCTION DistinctCount(arr ANY TYPE) AS (
      (SELECT COUNT(DISTINCT x) FROM UNNEST(arr) AS x)
    );
    
    WITH test AS
    (
      SELECT
      DATE('2018-01-01') as date,
      2 as value,
      [1,2,3] as key
      UNION ALL
      SELECT
      DATE('2018-01-02') as date,
      3 as value,
      [1,4,5] as key
    )
    
    SELECT
      SUM(value) as total_value,
      DistinctCount(ARRAY_CONCAT_AGG(key)) as unique_key_count
    FROM test
    

    这避免了有子查询或需要将数组与表连接起来(导致总和中的重复值)。

    【讨论】:

    • 这太好了,谢谢。我想在查询生成工具(Looker)中使用它,因此子查询方法实际上不适用于用例。有趣的是,当我用一堆数据尝试它时,它会慢很多。没有意识到 UDF 让事情变慢了这么多。下面的 HLL++ 方法要快得多,所以这可能是要走的路。
    【解决方案2】:

    以下是 BigQuery 标准 SQL

    #standardSQL
    WITH test AS
    (
      SELECT DATE('2018-01-01') AS DATE, 2 AS value, [1,2,3] AS key UNION ALL
      SELECT DATE('2018-01-02') AS DATE, 3 AS value, [1,4,5] AS key
    )
    SELECT 
      total_value,
      COUNT(DISTINCT key) unique_key_count
    FROM (
      SELECT
        SUM(value) AS total_value,
        ARRAY_CONCAT_AGG(key) AS all_keys
      FROM test
    ), UNNEST(all_keys) key
    GROUP BY total_value  
    

    结果:

    Row total_value unique_key_count     
    1   5           5     
    

    如果您的表中有很多行 - 您可以轻松解决内存/资源问题 - 在这种情况下,您可以尝试使用 HyperLogLog++ Functions 进行近似聚合 - 请参见下面的示例

    #standardSQL
    WITH test AS
    (
      SELECT DATE('2018-01-01') AS DATE, 2 AS value, [1,2,3] AS key UNION ALL
      SELECT DATE('2018-01-02') AS DATE, 3 AS value, [1,4,5] AS key
    )
    SELECT
      SUM(value) total_value,
      HLL_COUNT.MERGE((SELECT HLL_COUNT.INIT(key) FROM UNNEST(key) key)) AS unique_key_count
    FROM test
    

    结果

    Row total_value unique_key_count     
    1   5           5
    

    注意:这是近似聚合 - 所以要注意 HLL_COUNT.INIT(input [, precision]) 函数中的 precision 参数

    【讨论】:

    • 谢谢。之前没有玩过 HLL++ 函数
    • 这是答案的主要目的 - 介绍这些功能。他们通常被忽视:o)
    • 谢谢,这是使用 HLL++ 函数的一个很好的例子!!我发现官方文档非常缺乏清晰的示例(cloud.google.com/bigquery/docs/reference/standard-sql/…
    • @RogierWerschkull - 看看我最喜欢的 Google 员工之一的 Blog :o)
    • 虽然 HLL 方法有效,但我的客户想要精确的不同计数。为此,非 HLL 版本当然可以,但不能使用我们正在使用的 BI 工具 Looker 动态生成。还有其他方法可以实现吗?
    猜你喜欢
    • 2016-05-12
    • 2019-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    相关资源
    最近更新 更多