You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google BigQuery中大型表行复杂聚类的SQL实现问题

解决BigQuery交易ID聚类的连通分量问题

你之前用COALESCE组合多个独立聚类字段的思路是错的——因为那四个规则是传递关联的(比如a1和a2同组,a2和a3同组,那a1、a2、a3必须同组),而COALESCE只是取单个字段的非空值,完全没考虑不同聚类标识之间的连通性,自然会出现本该同组的ID被拆分、无关ID被错误合并的问题。

正确的思路是把所有规则转化为ID之间的关联边,然后用连通分量算法把所有互相连通的ID归为同一组。下面是具体实现步骤:

步骤1:标记ID首次出现时间(用于规则3)

先预计算每个ID的首次交易时间,判断该ID在某交易中是否是首次出现:

WITH id_first_occurrence AS (
  SELECT
    id,
    MIN(tx_timestamp) AS first_tx_time
  FROM `your_project.your_dataset.your_transaction_table`
  GROUP BY id
)

步骤2:生成所有关联边

根据四条规则,生成所有需要关联的ID对(边),避免重复或无效边:

, edges AS (
  -- 规则1:同一tx且is_type_0=TRUE的所有ID两两关联
  SELECT
    t1.id AS id1,
    t2.id AS id2
  FROM `your_project.your_dataset.your_transaction_table` t1
  JOIN `your_project.your_dataset.your_transaction_table` t2
    ON t1.tx_id = t2.tx_id
    AND t1.is_type_0 = TRUE
    AND t2.is_type_0 = TRUE
    AND t1.id < t2.id -- 避免双向重复边(如a1-a2和a2-a1)
  UNION DISTINCT
  -- 规则2:同一tx且is_type_1=FALSE的所有ID两两关联
  SELECT
    t1.id AS id1,
    t2.id AS id2
  FROM `your_project.your_dataset.your_transaction_table` t1
  JOIN `your_project.your_dataset.your_transaction_table` t2
    ON t1.tx_id = t2.tx_id
    AND t1.is_type_1 = FALSE
    AND t2.is_type_1 = FALSE
    AND t1.id < t2.id
  UNION DISTINCT
  -- 规则3:同一tx中is_type_1=TRUE且首次出现的ID,与同tx内其他ID关联
  SELECT
    t1.id AS id1,
    t2.id AS id2
  FROM `your_project.your_dataset.your_transaction_table` t1
  JOIN `your_project.your_dataset.your_transaction_table` t2
    ON t1.tx_id = t2.tx_id
    AND t1.is_type_1 = TRUE
    AND t1.tx_timestamp = (SELECT first_tx_time FROM id_first_occurrence WHERE id = t1.id)
    AND t1.id != t2.id -- 排除自关联
  UNION DISTINCT
  -- 规则4:单个ID自身的关联(确保孤立ID能形成独立组)
  SELECT
    id AS id1,
    id AS id2
  FROM `your_project.your_dataset.your_transaction_table`
)

步骤3:递归计算连通分量

用递归CTE遍历所有关联边,把连通的ID归为同一组(用根ID作为聚类标识):

, recursive_clusters AS (
  -- 初始化:每个ID作为自己的根节点
  SELECT
    id1 AS node,
    id1 AS cluster_root
  FROM edges
  UNION DISTINCT
  -- 递归遍历:合并关联的ID到同一根节点
  SELECT
    e.id2 AS node,
    r.cluster_root AS cluster_root
  FROM recursive_clusters r
  JOIN edges e
    ON r.node = e.id1
  WHERE e.id2 NOT IN (SELECT node FROM recursive_clusters)
)

步骤4:生成最终聚类结果

将原始表与聚类结果关联,得到每个ID对应的用户组:

SELECT
  t.id,
  -- 孤立ID(无任何关联)用自身作为聚类标识
  COALESCE(r.cluster_root, t.id) AS user_cluster_id
FROM `your_project.your_dataset.your_transaction_table` t
LEFT JOIN recursive_clusters r
  ON t.id = r.node
GROUP BY t.id, r.cluster_root
ORDER BY user_cluster_id, t.id

大表优化建议

如果你的表数据量极大,递归CTE可能遇到性能瓶颈,可以改用CONNECT BY语法实现连通分量(资源消耗更低):

WITH id_first_occurrence AS (
  SELECT id, MIN(tx_timestamp) AS first_tx_time
  FROM `your_project.your_dataset.your_transaction_table`
  GROUP BY id
),
all_nodes AS (
  SELECT DISTINCT id FROM `your_project.your_dataset.your_transaction_table`
),
edges AS (
  SELECT id1, id2 FROM (
    -- 规则1的边
    SELECT t1.id AS id1, t2.id AS id2
    FROM `your_project.your_dataset.your_transaction_table` t1
    JOIN `your_project.your_dataset.your_transaction_table` t2
      ON t1.tx_id = t2.tx_id AND t1.is_type_0 = TRUE AND t2.is_type_0 = TRUE
    UNION ALL
    -- 规则2的边
    SELECT t1.id AS id1, t2.id AS id2
    FROM `your_project.your_dataset.your_transaction_table` t1
    JOIN `your_project.your_dataset.your_transaction_table` t2
      ON t1.tx_id = t2.tx_id AND t1.is_type_1 = FALSE AND t2.is_type_1 = FALSE
    UNION ALL
    -- 规则3的边
    SELECT t1.id AS id1, t2.id AS id2
    FROM `your_project.your_dataset.your_transaction_table` t1
    JOIN `your_project.your_dataset.your_transaction_table` t2
      ON t1.tx_id = t2.tx_id AND t1.is_type_1 = TRUE AND t1.tx_timestamp = (SELECT first_tx_time FROM id_first_occurrence WHERE id = t1.id)
    UNION ALL
    -- 规则4的自关联边
    SELECT id, id FROM all_nodes
  )
  WHERE id1 != id2
)
SELECT
  id,
  CONNECT_BY_ROOT(id) AS user_cluster_id
FROM all_nodes
CONNECT BY NOCYCLE id = PRIOR id2 OR id = PRIOR id1
GROUP BY id, CONNECT_BY_ROOT(id)

这个方案会正确处理所有规则的传递关联,比如a1、a2、a3会因为a2同时关联a1和a3而被归为同一组,也不会出现无关ID错误聚类的问题。

内容的提问来源于stack exchange,提问作者smaica

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 04:01:19