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

BigQuery中按ID、版本取最高测试分数并转宽表的实现方法

BigQuery 测试分数行转宽表实现方案

原有写法问题说明

你之前编写的CTE+多表交叉查询存在两个核心问题:

  • 各版本临时表仅提取了分数字段,没有保留员工ID关联键,最后直接做笛卡尔交叉连接会导致员工和分数错配,无法得到正确结果
  • 手动枚举版本做临时表再join的方案,在版本数量多的时候维护成本极高,且如果员工缺失某版本成绩,join逻辑很容易漏数

最优实现方案

BigQuery原生提供PIVOT算子专门处理行转列场景,无需手写多表关联,代码简洁且性能更好,分两种场景使用:

1. 版本列表固定(推荐用于创建视图)

如果你的20个测试版本是稳定的、不会频繁增减,直接用静态PIVOT写法,写完可以直接基于该查询创建视图:

CREATE OR REPLACE VIEW `project.dataset.emp_max_score_wide` AS
WITH max_score_base AS (
  SELECT
    id,
    version,
    MAX(score) AS score
  FROM `project.dataset.table`
  WHERE
    type = 'assessment_test'
    AND id IS NOT NULL
    AND version IS NOT NULL
    AND score IS NOT NULL
  GROUP BY id, version
)
SELECT * FROM max_score_base
PIVOT(
  ANY_VALUE(score) -- 基础CTE已经聚合到id+version粒度,用ANY_VALUE/MAX都可
  FOR version IN (
    'version_a' AS version_a,
    'version_b' AS version_b,
    'version_c' AS version_c
    -- 按上述格式补全剩余版本即可
  )
)

该写法会自动以员工ID为行键,每个版本生成独立列存储对应最高分,员工缺失某版本成绩时自动填充NULL,不会漏数。

2. 版本动态变化(无需手动枚举版本)

如果测试版本会持续新增,不想每次更新版本都修改SQL,可以用BigQuery的动态SQL自动识别所有存在的版本生成列:

EXECUTE IMMEDIATE FORMAT("""
WITH max_score_base AS (
  SELECT
    id,
    version,
    MAX(score) AS score
  FROM `project.dataset.table`
  WHERE
    type = 'assessment_test'
    AND id IS NOT NULL
    AND version IS NOT NULL
    AND score IS NOT NULL
  GROUP BY id, version
)
SELECT * FROM max_score_base
PIVOT(
  ANY_VALUE(score)
  FOR version IN (%s)
)
ORDER BY id
""", (
  -- 子查询自动拉取所有去重后的版本名,生成PIVOT需要的列定义
  SELECT STRING_AGG(DISTINCT CONCAT("'", version, "' AS ", REPLACE(version, '.', '_')), ', ')
  FROM `project.dataset.table`
  WHERE
    type = 'assessment_test'
    AND version IS NOT NULL
));

注意:动态SQL生成的查询列数会随版本数变化,无法直接用于创建固定Schema的视图,适合临时查询、或者写入到固定结构的表中使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 13:01:05