You need to enable JavaScript to run this app. 如何在SQL中将长格式表转换为宽格式表
优惠活动
大模型
产品
解决方案
定价
更多

如何在SQL中将长格式表转换为宽格式表

长格式表转宽格式表的SQL实现方案

首先明确结论:该需求完全可以通过SQL实现,且绝大多数同表行转列场景下,不需要依赖UNION语法,通用写法的执行效率会远高于UNION相关的拼接方案。

你当前使用的是典型的EAV(实体-属性-值)长表结构,核心需求是将同一id下分散在多行的属性值,透传为单行下的多个独立列,也就是常见的行转列操作。

方案1:条件聚合(全场景优先推荐)

这是跨所有SQL方言兼容性最好、执行成本最低的实现方式,仅需一次全表扫描即可完成透视,没有重复扫描的额外开销。
对应的查询写法如下,假设你的长表表名为eav_data:

SELECT
  id,
  -- 匹配key为users的行,取出对应的value作为users列
  MAX(CASE WHEN `key` = 'users' THEN value END) AS users,
  -- 匹配key为politics的行,取出对应的value作为politics列
  MAX(CASE WHEN `key` = 'politics' THEN value END) AS politics
FROM eav_data
-- 按id分组,把同一实体的所有属性值聚合到同一行
GROUP BY id;

逻辑说明:

  • 按id做分组后,同一个id对应的所有key、value都会被纳入同一个聚合组
  • 通过CASE判断筛选出匹配目标key的行,取出对应的value
  • 因为同一id下每个key只会出现1次,这里搭配MAX/MIN这类聚合函数,不会出现数值被错误覆盖的问题,能准确取出对应的值
  • 按照你提供的示例数据,该查询返回的结果和预期的宽表完全匹配:id=1行的users值为67、politics值为45,id=2行的users值为42、politics值为89。

方案2:UNION拼接实现

如果你最初抱着用UNION解决问题的思路探索,该场景下也可以通过UNION完成,只是性能会弱于方案1。常见写法是先针对每个key单独过滤出对应的数据,给其他目标列填充空值,再通过UNION拼接所有分支的结果,最后按id聚合合并同一行的空值与实际值:

SELECT
  id,
  MAX(users) AS users,
  MAX(politics) AS politics
FROM (
  -- 取出users属性的所有行
  SELECT id, value AS users, NULL AS politics
  FROM eav_data
  WHERE `key` = 'users'
  
  UNION ALL
  
  -- 取出politics属性的所有行
  SELECT id, NULL AS users, value AS politics
  FROM eav_data
  WHERE `key` = 'politics'
) AS union_result
GROUP BY id;

两种方案的性能差异:

  • 该UNION写法会触发至少2次原表扫描(每个key对应的过滤查询各扫一次表),数据量越大时性能和方案1的差距越明显
  • 这种UNION写法最终还是需要通过聚合合并数据,执行逻辑本质上和方案1趋同,没有额外的灵活性优势,仅适合用来理解UNION的作用,实际生产环境不推荐使用。

补充说明:部分数据库支持专属的PIVOT透视函数,本质也是对条件聚合逻辑的语法封装,在固定列的行转列场景下,不如手写CASE WHEN的写法兼容性好、调试方便。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.03 16:45:04