【问题标题】:Match records using BigQuery SQL syntax使用 BigQuery SQL 语法匹配记录
【发布时间】:2020-12-29 07:41:39
【问题描述】:

我的表包含一些标识符,称它们为 ID1 和 ID2,记录如下所示:

ID1   ID2
01    1
01    1
01    2
01    2
01    2
02    2
02    2
02    3
02    3
02    3
...
03    4
04    5
05    6
06    7

因为我可以在示例表的第一部分通过ID1 = 02ID2 = 3 链接到ID2 = 2,然后通过ID2 = 2ID1 = 02 链接到ID2 = 01,我知道这是一个单一的实体,我'我感兴趣。

是否可以从 ID1 创建一个复合键,这表明这是一个单一的实体,例如:

ID1   ID2   ID_comp
01    1     01_02
01    1     01_02
01    2     01_02
01    2     01_02
01    2     01_02
02    2     01_02
02    2     01_02
02    3     01_02
02    3     01_02
02    3     01_02
03    4     03
04    5     04
05    6     05
06    7     06

这只是一个例子。在 ID1 和 ID2 中可能有更长的序列和多个标识符。另请注意,ID1 的某些序列直接映射到 ID2,例如 03、04、05、06。ID1 和 ID2 都是全局唯一的字符串,但为简单起见,我在这里使用了数字。还有一个时间戳列,可以用来对记录进行排序。

任何帮助表示赞赏。

【问题讨论】:

    标签: google-bigquery


    【解决方案1】:

    以下内容适用于 BigQuery 标准 SQL 和使用 BQ 脚本功能

    DECLARE rows_count, run_away_stop INT64 DEFAULT 0;
    
    CREATE TEMP TABLE buckets AS 
    SELECT ARRAY_AGG(id2 ORDER BY id2) arr 
    FROM `project.dataset.table`
    GROUP BY id1;
    
    LOOP
      SET rows_count = (SELECT COUNT(1) FROM buckets);
      SET run_away_stop = run_away_stop + 1;
    
      CREATE OR REPLACE TEMP TABLE buckets AS
      SELECT ANY_VALUE(arr) arr FROM (
        SELECT ARRAY(SELECT DISTINCT val FROM UNNEST(arr) val ORDER BY val) arr
        FROM (
          SELECT ANY_VALUE(arr1) arr1, ARRAY_CONCAT_AGG(arr) arr    
          FROM (
            SELECT t1.arr arr1, t2.arr arr2, ARRAY(SELECT DISTINCT val FROM UNNEST(ARRAY_CONCAT( t1.arr, t2.arr)) val ORDER BY val) arr 
            FROM buckets t1, buckets t2 
            WHERE (SELECT COUNT(1) FROM UNNEST(t1.arr) val JOIN UNNEST(t2.arr) val USING(val)) > 0
          ) GROUP BY FORMAT('%t', arr1)
        )
      ) GROUP BY FORMAT('%t', arr);
    
      IF (rows_count = (SELECT COUNT(1) FROM buckets) AND run_away_stop > 1) OR run_away_stop > 10 THEN BREAK; END IF;
    END LOOP;
    
    SELECT id1, id2, 
      ARRAY_TO_STRING(ARRAY(SELECT DISTINCT id FROM t.arr as id ORDER BY id), '_') ID_comp
    FROM (
      SELECT id1, id2, ARRAY_AGG(id1) OVER(PARTITION BY grp) arr 
      FROM input 
      JOIN (SELECT ROW_NUMBER() OVER() grp, arr FROM buckets) 
      ON id2 IN UNNEST(arr) 
    ) t
    -- ORDER BY id1, id2;     
    

    如果将上述脚本应用于您的问题中的样本数据 - 输出是

    注意:要查看上面的结果,您需要单击脚本中最后一条语句的 VIEW RESULTS 按钮 - 运行脚本后将如下所示

    另请注意 - 您可以通过调整 run_away_stop > 10 来控制循环的收敛 - 正如您现在看到的,只允许 10 次迭代 - 您可以根据需要增加它

    【讨论】:

    • 哇,非常感谢!这真的很有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多