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

MySQL 5.7.36实现分组行转列:将多行联系人电话转为多列

MySQL 5.7 实现分组行转列(拆分电话号码为3列)方案

MySQL 5.7 版本未内置ROW_NUMBER() OVER()窗口函数,无法直接照搬SQL Server的写法,可通过用户自定义变量模拟分组序号+条件聚合的方式实现需求,具体步骤如下:

核心实现逻辑

  1. 用会话变量遍历表数据,按idservicio、idcliente分组,给同组内的记录按指定顺序生成1、2、3的递增序号,跨组时序号自动重置为1
  2. 基于生成的组内序号,用条件判断把对应序号的电话号码拆分到独立列,通过分组聚合合并同组数据,不足3个号码的位置留空

可直接运行的最终SQL

SELECT
  idservicio,
  idcliente,
  -- 若需要对应每个号码的联系人姓名,可参照telefono的写法拆分为contacto1/2/3三列
  MAX(`nombre contacto`) AS nombre_contacto,
  MAX(CASE WHEN row_num = 1 THEN telefono ELSE NULL END) AS `telefono 1`,
  MAX(CASE WHEN row_num = 2 THEN telefono ELSE NULL END) AS `telefono 2`,
  MAX(CASE WHEN row_num = 3 THEN telefono ELSE NULL END) AS `telefono 3`
FROM (
  SELECT
    idservicio,
    idcliente,
    `nombre contacto`,
    telefono,
    -- 组内序号生成:当前分组和上一条记录一致则序号+1,否则重置为1
    @rn := IF(
      @grp_s = idservicio AND @grp_c = idcliente,
      @rn + 1,
      1
    ) AS row_num,
    -- 暂存当前分组字段值,供下一条记录比对
    @grp_s := idservicio,
    @grp_c := idcliente
  FROM
    contact,
    -- 初始化用户变量
    (SELECT @rn := 0, @grp_s := NULL, @grp_c := NULL) AS var_init
  -- 必须指定排序规则,保证同组号码的取数顺序稳定,可按业务需求调整排序字段
  ORDER BY idservicio, idcliente, `nombre contacto`
) AS tmp
-- 仅保留每组前3个号码,超出部分自动忽略
WHERE row_num <= 3
GROUP BY idservicio, idcliente

注意事项

  • 子查询中的ORDER BY不可省略,否则同组内号码的排列顺序无保障,每次查询可能返回不同的telefono 1/2/3结果
  • 若需要空缺位置返回空字符串而非NULL,将SQL中ELSE NULL替换为ELSE ''即可
  • 字段名nombre contacto包含空格,所有引用位置必须加反引号包裹,否则会触发语法错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 12:16:02