MySQL 5.7.36实现分组行转列:将多行联系人电话转为多列
MySQL 5.7 实现分组行转列(拆分电话号码为3列)方案
MySQL 5.7 版本未内置ROW_NUMBER() OVER()窗口函数,无法直接照搬SQL Server的写法,可通过用户自定义变量模拟分组序号+条件聚合的方式实现需求,具体步骤如下:
核心实现逻辑
- 用会话变量遍历表数据,按
idservicio、idcliente分组,给同组内的记录按指定顺序生成1、2、3的递增序号,跨组时序号自动重置为1 - 基于生成的组内序号,用条件判断把对应序号的电话号码拆分到独立列,通过分组聚合合并同组数据,不足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
相关产品推荐
相关产品推荐

