如何基于GROUP BY在SQL视图中合并行?附示例表结构
基于GROUP BY实现多行转多列的视图创建方案
首先明确你的需求:把原始表中同一c1对应的多行c2值,转成横向的多列(c2、c3)并创建视图,核心要基于GROUP BY实现。下面分不同数据库给出具体方案,核心思路是条件聚合 + 分组内序号标记。
假设你的原始表名为your_table,数据结构和内容如下:
| c1 | c2 |
|---|---|
| A | B |
| A | C |
| X | P |
| X | Q |
核心思路
要实现多行转多列,我们需要先给每个c1分组内的行分配一个唯一序号,然后通过GROUP BY c1,配合CASE语句和聚合函数(比如MAX),把不同序号对应的c2值提取到对应的列中。
1. MySQL 实现方案
MySQL旧版本没有原生窗口函数,可以用用户变量生成分组内的序号:
-- 创建视图 CREATE VIEW c1_crosstab AS SELECT c1, -- 提取分组内第1个c2值作为c2列 MAX(CASE WHEN seq = 1 THEN c2 END) AS c2, -- 提取分组内第2个c2值作为c3列 MAX(CASE WHEN seq = 2 THEN c2 END) AS c3 FROM ( -- 子查询:给每个c1分组内的行分配序号 SELECT c1, c2, @row_num := CASE WHEN @prev_c1 = c1 THEN @row_num + 1 ELSE 1 END AS seq, @prev_c1 := c1 FROM your_table, (SELECT @row_num := 0, @prev_c1 := '') AS init_vars -- 排序保证序号顺序符合预期(按c1、c2排序) ORDER BY c1, c2 ) AS ranked_rows GROUP BY c1;
2. PostgreSQL / SQL Server 实现方案
这两个数据库支持窗口函数,用ROW_NUMBER()会更简洁:
-- 创建视图 CREATE VIEW c1_crosstab AS SELECT c1, MAX(CASE WHEN seq = 1 THEN c2 END) AS c2, MAX(CASE WHEN seq = 2 THEN c2 END) AS c3 FROM ( -- 子查询:用窗口函数生成分组内的序号 SELECT c1, c2, ROW_NUMBER() OVER (PARTITION BY c1 ORDER BY c2) AS seq FROM your_table ) AS ranked_rows GROUP BY c1;
扩展说明
- 如果某个
c1对应更多的c2值(比如3个),只需要继续添加MAX(CASE WHEN seq = 3 THEN c2 END) AS c4这样的列即可。 ORDER BY子句可以根据你的需求调整,比如如果不需要按c2排序,改成其他字段或者去掉(但建议保留,保证结果顺序稳定)。- 这里用
MAX聚合函数是因为每个seq在分组内唯一,MAX和MIN效果一致,任选其一即可。
内容的提问来源于stack exchange,提问作者S_S
相关产品推荐
相关产品推荐

