sql行转列的技巧

比方说现在这么一张数据表

 成绩表grade,里边存储了student_id学生编号,subject_id科目编号,grade成绩。表里每一条数据代表一个学生的一门科目的成绩。其中subject_id 1代表语文,2代表数学,3代表英语。

现有需求,要求生成一张报表,表头是学生ID,语文科目成绩、数学科目成绩,英语科目成绩。而表里的每一行代表一个科目的成绩,需求却需要将三门科目的成绩变为一行,那该怎么办呀?

再应用里做,那还需要应用端单独开发去整理数据。如果该没有应用那又该怎么办呢?

其实可以用sql的聚合函数和if函数嵌套来实现本需求(oracle可以用sum和decode)

--  mysql
  SELECT   grade.student_id,
  SUM(if(grade.subject_id='1',grade.grade,0)) 语文成绩,
  SUM(if(grade.subject_id='2',grade.grade,0)) 数学成绩,
  SUM(if(grade.subject_id='3',grade.grade,0)) 英语成绩
  FROM grade  GROUP BY
  grade.student_id
  -- oracle
    SELECT   grade.student_id,
  SUM(decode(grade.subject_id,'1',grade.grade,0)) 语文成绩,
  SUM(decode(grade.subject_id,'2',grade.grade,0)) 数学成绩,
  SUM(decode(grade.subject_id,'3',grade.grade,0)) 英语成绩
  FROM grade  GROUP BY
  grade.student_id

用if函数或者decode函数对每一行的subject_id进行判断,如果是对应科目编号,就返回grade,否则返回0。然后用sum根据student_id去进行汇总。这样嵌套使用相当于对应科目的成绩+0+0。这样就满足了需求。

这里要注意一下,行转列的聚合函数一定要用sum不要用count。假设有需求改变,需要统计每门课程的及格次数。要用sum(if(grade>=60,1,0))不要用count,因为count不管该数据列是什么,只要where条件没有过滤,则都算一条。sum可以用if将不符合要求的数据行变为0来过滤。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值