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

如何在BigQuery/MySQL/SQLAlchemy中合并含JSON的两行为单行

同SID双JSON记录合并实现方案

针对同一sid关联2条独立记录、每条记录data字段存储独立JSON对象的场景,目标聚合结果为单条sid记录,data字段结构为{"1": 第一条原JSON, "2": 第二条原JSON},以下是不同环境的可直接运行实现:

  • BigQuery 环境
    利用原生JSON函数+窗口函数保证顺序稳定,若data字段为字符串存储的JSON,替换为PARSE_JSON(data)即可:

    WITH ranked AS (
      SELECT
        sid,
        data,
        ROW_NUMBER() OVER (PARTITION BY sid ORDER BY create_time ASC) AS rn -- 排序字段可按业务规则替换
      FROM your_source_table
      QUALIFY COUNT(1) OVER (PARTITION BY sid) = 2 -- 仅保留恰好2条记录的sid,避免脏数据
    )
    SELECT
      sid,
      JSON_OBJECT(
        '1', MAX(IF(rn = 1, data, NULL)),
        '2', MAX(IF(rn = 2, data, NULL))
      ) AS data
    FROM ranked
    GROUP BY sid
    
  • MySQL 环境
    8.0及以上版本支持窗口函数,写法简洁:

    WITH ranked AS (
      SELECT
        sid,
        data,
        ROW_NUMBER() OVER (PARTITION BY sid ORDER BY id ASC) AS rn -- 按主键排序保证顺序固定
      FROM your_source_table
    )
    SELECT
      sid,
      JSON_OBJECT(
        '1', MAX(CASE WHEN rn = 1 THEN data END),
        '2', MAX(CASE WHEN rn = 2 THEN data END)
      ) AS data
    FROM ranked
    GROUP BY sid
    HAVING COUNT(*) = 2;
    

    5.7版本无窗口函数,可通过自关联实现:

    SELECT
      t1.sid,
      JSON_OBJECT(
        '1', MIN(IF(t1.id < t2.id, t1.data, t2.data)),
        '2', MAX(IF(t1.id < t2.id, t1.data, t2.data))
      ) AS data
    FROM your_source_table t1
    INNER JOIN your_source_table t2 
      ON t1.sid = t2.sid AND t1.id <> t2.id
    GROUP BY t1.sid
    HAVING COUNT(*) = 2;
    
  • SQLAlchemy 环境
    以适配MySQL8.0/BigQuery的ORM写法为例,可直接集成到现有代码逻辑:

    from sqlalchemy import func, select, case
    from your_models import YourTable # 替换为实际业务表模型
    
    # 构造带行号的CTE子查询
    ranked_cte = (
        select(
            YourTable.sid,
            YourTable.data,
            func.row_number()
                .over(partition_by=YourTable.sid, order_by=YourTable.id.asc())
                .label("rn")
        )
        .cte("ranked_data")
    )
    
    # 构造最终聚合查询
    merge_query = (
        select(
            ranked_cte.c.sid,
            func.json_object(
                "1", func.max(case((ranked_cte.c.rn == 1, ranked_cte.c.data))),
                "2", func.max(case((ranked_cte.c.rn == 2, ranked_cte.c.data)))
            ).label("data")
        )
        .group_by(ranked_cte.c.sid)
        .having(func.count() == 2)
    )
    
    # 执行查询获取结果
    # result = session.execute(merge_query).all()
    

    若使用的数据库方言对JSON函数名有差异,替换func.json_object为对应函数即可,比如BigQuery下无需修改,SQLAlchemy会自动适配大小写。

注意:所有实现中的排序字段必须可以唯一区分同sid下的两条记录,否则会出现键1、键2对应内容随机的问题;如果后续需要合并同sid下超过2条记录,只需扩展JSON_OBJECT的键值对、匹配对应行号即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 16:15:37