zoukankan      html  css  js  c++  java
  • SQL 强化练习 (十)

    这一周都被客户搞得很惨.... 项目主流程不推进, 尽搞一些无关紧要的事情, 什么界面 ui 美化, 增加什么按钮进度条, 模糊查询...各种乱七八糟的需求, 挡都挡不住呀... 真的是把我当全栈使了, 数据库, 建表; 填报页面, 数据清洗, ui 美化, 权限配置 sql ... 真的太难了.... 发现核心呢, 还是 sql 的比重特别大, 像我们现在数据分析用的 BI 工具, 就是 以 SQL为基础的. 反而, 用 Pyhton 的地方却是很少, 跟我之前的项目差别很大, 这里用Pyhton 就只是一些做数据清洗的事情, 如过滤数据中的特殊字符 (正则) , 类型转换, 顺序调整的... 核心竞争还是 sql 呀. 果然 sql 非常强大. 继续练习呀...

    表关系

    我平时遇到的一些复杂些的业务场景, 基本也跟着几张表, 背后的相同逻辑所演变的. 都差不多的其实.

    需求 01

    查询各科成绩最高分, 最低分和平均分; 显示需求如下:

    课程id, 课程 name, 最高分, 最低分, 平均分, 及格率, 中等率, 优良率, 优秀率

    及格 >= 60; 中等:70-80; 优良: 80-90; 优秀: >=90

    分析

    目测会用到 group by case when ...

    首先来查询, 课程的最高, 最低, 平均分的 (聚合函数, 肯定是结合 group by)

    select 
      a.c_id, 
      b.c_name,
      max(a.score), 
      min(a.score),
      avg(a.score)
    
    from score  as a 
    -- 课程 name 是需要关联课程表才能拿到
    inner join course as b 
      on a.c_id = b.c_id
    group by a.c_id, b.c_name
    
    +------+--------+--------------+--------------+--------------+
    | c_id | c_name | max(a.score) | min(a.score) | avg(a.score) |
    +------+--------+--------------+--------------+--------------+
    | 0001 | 语文   |           80 |           80 |      80.0000 |
    | 0002 | 数学   |           90 |           60 |      76.6667 |
    | 0003 | 英语   |           99 |           80 |      86.3333 |
    +------+--------+--------------+--------------+--------------+
    3 rows in set (0.01 sec)
    
    

    这一部分其实还好, 就是基本的 group by 再聚合而已.

    接着来算这些什么中等率, 优良率, 优秀率.. 就有些头疼了. 率, 是要用 目标人数 / 总人数 这样的方式. 立马会想到用 count 但, 这里多条件判断嘛, 必然会用 case when 来处理呀. 其实呢, 用 sum 可能会更加普遍一点. 满足条件就舌标记为1, 否则标记 0 这样的方式.

    select 
      a.c_id, 
      b.c_name,
      max(a.score), 
      min(a.score),
      avg(a.score), 
      -- 及格率
      sum(case when a.score >= 60 then 1 else 0 end) / count(a.s_id) "及格率", 
      -- 中等率
      sum(case when a.score >= 70 and a.score < 80 then 1 else 0 end) / count(a.s_id) "中等率",
      -- 优良率
      sum(case when a.score >= 80 and a.score < 90 then 1 else 0 end) / count(a.s_id) "优良率",
      -- 优秀率
      sum(case when a.score >= 90 then 1 else 0 end) / count(a.s_id) as "优秀率"
    
    from score  as a 
    -- 课程 name 是需要关联课程表才能拿到
    inner join course as b 
      on a.c_id = b.c_id
    group by c_id, c_name
    
    

    这个例子的关键点, 首先还是基于分组, 聚合 的用法, 中间过程呢, 会涉及表的拼接(inner join). 然后是 case when 可用来做条件计数 这个感觉蛮厉害的, 我其实在工作中都没用过. 类似的我都用 Python 来搞了, 没想到这 sql 原来还这么强大的哦.

    需求 02

    查询学生的总成绩, 并进行排名

    分析

    一个基础送分题, 按 s_id 分组, 对 score 统计即可.

    select 
      s_id as "学号",
      sum(score) as "总成绩"
    from score 
    group by s_id
    
    
    +--------+-----------+
    | 学号   | 总成绩    |
    +--------+-----------+
    | 0001   |       269 |
    | 0002   |       140 |
    | 0003   |       240 |
    +--------+-----------+
    3 rows in set (0.00 sec)
    
    mysql>
    

    然后排序一波即可. (把姓名也 inner join 过来顺带)

    select 
      a.s_id as "学号",
      b.s_name as "姓名",
      sum(a.score) as "总成绩"
    
    
    from score as a
    -- 学生信息帖过来
    inner join student as b 
      on a.s_id = b.s_id
    
    group by a.s_id, b.s_name
    order by sum(score) desc
    
    
    +--------+-----------+-----------+
    | 学号   | 姓名      | 总成绩    |
    +--------+-----------+-----------+
    | 0001   | 王二      |       269 |
    | 0003   | 胡小适    |       240 |
    | 0002   | 星落      |       140 |
    +--------+-----------+-----------+
    3 rows in set (0.00 sec)
    
    -- 这一句感觉怪怪的, 应该用上面别名的.
    order by sum(score) desc
    

    最后修改如下:

    select 
      a.s_id as 学号,
      b.s_name as 姓名,
      sum(a.score) as 总成绩
    
    
    from score as a
    -- 学生信息帖过来
    inner join student as b 
      on a.s_id = b.s_id
    
    group by a.s_id, b.s_name
    order by 总成绩 desc  
    
    
    +--------+-----------+-----------+
    | 学号   | 姓名      | 总成绩    |
    +--------+-----------+-----------+
    | 0001   | 王二      |       269 |
    | 0003   | 胡小适    |       240 |
    | 0002   | 星落      |       140 |
    +--------+-----------+-----------+
    3 rows in set (0.00 sec)
    

    可以, 发现, 在 mysql 中, 可以直接用 中文 作为别名.

    小结

    • sum(case when ..then 1 else 0 end) 可以用来进行 条件计数哦 (配合 group by )
    • 表 join 可以在中途进行, 理清楚 sql 的执行顺序即可 from > on > join > where > group by > having > select > distinct > order by
    • 发现 mysql 中, 别名可以直接使用中文, 比如 之前是 xxx as "总成绩", 也可直接 xxx as 总成绩 .
  • 相关阅读:
    [转] Immutable 常用API简介
    [转] 组件库按需加载 借助babel-plugin-import实现
    [转] react-router4 + webpack Code Splitting
    [转] React Hot Loader 3 beta 升级指南
    [转] 如何写好.babelrc?Babel的presets和plugins配置解析
    [转] webpack热更新配置小结
    [转] 学会fetch的用法
    [转] webpack3.0踩坑:postcss-loader的使用
    [转] 详解webpack-dev-server的使用
    webpack 使用环境变量
  • 原文地址:https://www.cnblogs.com/chenjieyouge/p/12681282.html
Copyright © 2011-2022 走看看