个人随笔
目录
Oracle行转列例子
2022-07-11 11:49:36

Oracle行转列核心逻辑+实操笔记

一、行转列 “万能口诀”(核心逻辑)

这两句口诀是行转列的底层逻辑,适用于所有场景:

  1. 分组列定行数,分类列定列数,值字段填内容;

  2. CASE WHEN 判 “分类列的取值”,THEN 填 “值字段的内容”。

二、口诀与代码对应关系(原奖品表例子验证)

核心口诀 对应 Oracle 代码片段 落地解释
分组列定行数 GROUP BY user_name 分组列是user_name,结果行数 = 分组数(张三、李四→2 行)
分类列定列数 CASE WHEN t.award_name = ‘ 手机 ‘/‘ 大米’ 分类列是award_name,取值数量决定基础列数
值字段填内容 THEN t.award_name / THEN t.create_date 值字段是award_name(奖品名)和create_date(日期),填充到新列
CASE WHEN 判 “分类列的取值” WHEN t.award_name = ‘ 手机’ 仅判断分类列的具体值,而非直接使用分类列
THEN 填 “值字段的内容” THEN t.create_date 满足判断条件后,填充对应值字段的内容

三、关键避坑提醒

  1. 列数计算公式:最终列数 = 分类列的取值数量 × 值字段数量

    示例验证:分类列取值(手机、大米→2 个)× 值字段(奖品名、日期→2 个)= 4 列(shouji、shouji_create_date、dami、dami_create_date);

    若仅保留 1 个值字段(如仅日期),则列数 = 2×1=2 列(手机日期、大米日期)。

  2. 聚合函数使用:需用MAX()/MIN()/SUM()等聚合函数包裹 CASE WHEN,避免分组后出现多行重复数据(因同一分组下可能有多个匹配记录,聚合函数取唯一有效值)。

  3. 默认值处理:建议用NULL替代'0'作为 ELSE 结果(日期字段填'0'会导致类型异常,字符串字段填NULL更符合 “无数据” 语义)。

四、原奖品表完整可执行 SQL(优化后)

  1. SELECT
  2. t.user_name,
  3. -- 手机相关列
  4. MAX(CASE WHEN t.award_name = '手机' THEN t.award_name ELSE NULL END) AS shouji,
  5. MAX(CASE WHEN t.award_name = '手机' THEN t.create_date ELSE NULL END) AS shouji_create_date,
  6. -- 大米相关列
  7. MAX(CASE WHEN t.award_name = '大米' THEN t.award_name ELSE NULL END) AS dami,
  8. MAX(CASE WHEN t.award_name = '大米' THEN t.create_date ELSE NULL END) AS dami_create_date
  9. FROM award t
  10. WHERE t.award_name IN ('手机', '大米') -- 过滤分类列取值,优化性能
  11. GROUP BY t.user_name;

五、新场景实操:成绩分数行转列(验证通用性)

场景说明

现有成绩表score,字段:student_name(学生姓名)、subject(科目)、score(分数)、exam_date(考试日期);

需求:行转列展示每个学生的「语文分数、语文考试日期、数学分数、数学考试日期」,每个学生仅 1 行数据。

套用口诀写 SQL

  1. 分组列:student_name(定行数→学生数量 = 结果行数);

  2. 分类列:subject(定列数→取值:语文、数学→2 个);

  3. 值字段:score(分数)、exam_date(考试日期)→2 个;

  4. 最终列数:2×2=4 列(语文分数、语文日期、数学分数、数学日期)。

完整 SQL 代码

  1. SELECT
  2. student_name,
  3. -- 语文相关列(分类列取值=语文,值字段=分数/日期)
  4. MAX(CASE WHEN subject = '语文' THEN score ELSE NULL END) AS chinese_score,
  5. MAX(CASE WHEN subject = '语文' THEN exam_date ELSE NULL END) AS chinese_exam_date,
  6. -- 数学相关列(分类列取值=数学,值字段=分数/日期)
  7. MAX(CASE WHEN subject = '数学' THEN score ELSE NULL END) AS math_score,
  8. MAX(CASE WHEN subject = '数学' THEN exam_date ELSE NULL END) AS math_exam_date
  9. FROM score
  10. WHERE subject IN ('语文', '数学') -- 过滤无关科目
  11. GROUP BY student_name
  12. ORDER BY student_name; -- 按学生姓名排序,优化阅读

示例数据与执行结果

student_name chinese_score chinese_exam_date math_score math_exam_date
小明 92 2024-06-10 88 2024-06-11
小红 95 2024-06-10 93 2024-06-11

六、总结

  1. 行转列本质:通过「分组列聚合 + 分类列判断 + 值字段填充」,将多行数据压缩为一行;

  2. 口诀是核心:无论场景如何变化,只要确定「分组列、分类列取值、值字段」,就能直接套用;

  3. 避坑关键:记住列数计算公式,用聚合函数包裹 CASE WHEN,默认值用NULL

(注:文档部分内容可能由 AI 生成)

 360

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2