SQL 强化练习 (五)

果然日常练练这些 sql 是非常有必要的, 这几日的报表开发, 用一款过程软件 fineReport, 相对于我之前用 Tableau 来做报表, 这个帆软, 确实更加适合中国人哦, 而Tableau只是专门用来展示而已. 我感觉 FR, 还是有一定门槛的, 首先就是 SQL, 大量的操作都是需要写 sql 来完成的, 我还蛮喜欢的其实, 很灵活的嘛. 其实是要理解 WEB, 比如做填报, 就是要先弄个页面, 然后设计数据库, 单元格值回写数据库, 数据库查询报表展示... 这个就是 WEB 呀, 反正我觉得还是有些复杂的, 但核心技能 SQL 是必须的, 虽然这里用的更多是 查询方面. 还是得不断练习...

表关系

深深可在脑海中, 我感觉, 其实业务中也只不过是, 字段变多了, 表结构复杂一些而已, 本质是还是表呀.

需求 01

查询课程编号为 "0002" 的总成绩, 平均成绩, 人数等.

分析

这就是用来练习下聚合函数(sum, count, avg..)

select
  sum(score) as "总成绩",
  avg(score) as "平均成绩",
  count(score) as "成绩总份数",
  count(distinct s_id) as "学生人数"

from score
where c_id = "0002";

+-----------+--------------+-----------------+--------------+
| 总成绩    | 平均成绩     | 成绩总份数      | 学生人数     |
+-----------+--------------+-----------------+--------------+
|       230 |      76.6667 |               3 |            3 |
+-----------+--------------+-----------------+--------------+

感觉其实这个查询是没啥意义的, 就选一个一门课, 有啥号看的呢, 倒不如, 查看所有的课程的信息多好.

select
  c_id  as "课程编号",
  sum(score) as "总成绩",
  avg(score) as "平均成绩",
  count(score) as "成绩总份数",
  count(distinct s_id) as "学生人数"
from score 

group by c_id; 

+--------------+-----------+--------------+-----------------+--------------+
| 课程编号     | 总成绩    | 平均成绩     | 成绩总份数      | 学生人数     |
+--------------+-----------+--------------+-----------------+--------------+
| 0001         |       160 |      80.0000 |               2 |            2 |
| 0002         |       230 |      76.6667 |               3 |            3 |
| 0003         |       259 |      86.3333 |               3 |            3 |
+--------------+-----------+--------------+-----------------+--------------+

这样, 看全部的数据, 我感觉这更加贴和业务一点. 值得主要的是 group by 的用法, select 一般都先是这个 聚合字段的值, 然后再是一些聚合函数字段. 不要再select 放跟 分组字段 没有关系的字段. 这样经常会引发歧义和直接报错, group by -> aggregation... 这是必须要掌握的哦. 其次, 就是 group by 后面不要跟 where, 根本没有意义, where 必然是要放在 group by 之前呀, 而对于 分组后的过滤 用 having.

正好来练习一下: 用分组过滤 having 的方式来查看 "0002" 的信息

select 

  c_id  as "课程编号",
  sum(score) as "总成绩",
  avg(score) as "平均成绩",
  count(score) as "成绩总份数",
  count(distinct s_id) as "学生人数"
from score 

group by c_id having c_id = "0002";

一样的结果

+--------------+-----------+--------------+-----------------+--------------+
| 课程编号     | 总成绩    | 平均成绩     | 成绩总份数      | 学生人数     |
+--------------+-----------+--------------+-----------------+--------------+
| 0002         |       230 |      76.6667 |               3 |            3 |
+--------------+-----------+--------------+-----------------+--------------+
1 row in set (0.00 sec)

我感觉我每天都是在干这类似的 筛选字段, 分组聚合的活. 原本我以为会了 Pandas 就无所畏惧, 为所欲为, 结果, 工作中更多是要去从数据库中查询数据 用sql 的方式来查询返回, 而非用 Python 来搞, 我感觉 Python 我搞得更多的是一些线下的表格数据, 什么 Excel, csv, json... 无敌强, 但更多还是用 sql 来查询数据会更通用和专业些.

需求 02

查询 所有课程成绩小于 90 分 的学生学号, 姓名

分析

先用学号进行 group by (结合 where 成绩 < 90) 的课程数量;

然后再统计, 该学号总共选了几门课, 这样一比较就好啦.

我还是先自己肉眼给看一眼:

select 

  s_id as "学号",
  c_id as "课程号",
  score as "成绩"

from score 

group by s_id, c_id;
+--------+-----------+--------+
| 学号   | 课程号    | 成绩   |
+--------+-----------+--------+
| 0001   | 0001      |     80 |
| 0001   | 0002      |     90 |
| 0001   | 0003      |     99 |
| 0002   | 0002      |     60 |
| 0002   | 0003      |     80 |
| 0003   | 0001      |     80 |
| 0003   | 0002      |     80 |
| 0003   | 0003      |     80 |
+--------+-----------+--------+
8 rows in set (0.00 sec)

这样一看, 都是满足的呀.


-- 首先呢, 先看看每个人成绩小于 90 分的 课有几门

select
  s_id as "学号",
  count(c_id) as "小于90的课数"

from score
where score < 90

group by s_id;
+--------+-------------------+
| 学号   | 小于90的课数      |
+--------+-------------------+
| 0001   |                 1 |
| 0002   |                 2 |
| 0003   |                 3 |
+--------+-------------------+
3 rows in set (0.00 sec)

-- 然后呢, 再看看每个人一个选课几门课

select
  s_id as "学号",
  count(c_id) as "选课数"

from score 

group by s_id;
+--------+-----------+
| 学号   | 选课数    |
+--------+-----------+
| 0001   |         3 |
| 0002   |         2 |
| 0003   |         3 |
+--------+-----------+
3 rows in set (0.00 sec)

再将这两个表一拼 inner join 不就美滋滋.. 即 inner 上的学号就是不满足条件的呀

select
  a.*,
  b.*

from
(
  select

    s_id as "学号",
    count(c_id) as "小于90的课数"

  from score 

  where score < 90

  group by s_id) as a  

inner join

(
  select
    s_id as "学号",
    count(c_id) as "选课数"

  from score 

  group by s_id) as b

on a.学号= b.学号;

+--------+-------------------+--------+-----------+
| 学号   | 小于90的课数      | 学号   | 选课数    |
+--------+-------------------+--------+-----------+
| 0001   |                 1 | 0001   |         3 |
| 0002   |                 2 | 0002   |         2 |
| 0003   |                 3 | 0003   |         3 |
+--------+-------------------+--------+-----------+
3 rows in set (0.00 sec)

最后来个完整的. 我一般是从里到外的. 不断 select , 面向过程多一些.

select
 s_id as "学号",
 s_name as "姓名"

from student

where s_id in (

  select
    a.学号
  from
  (
    select

      s_id as "学号",
      count(c_id) as "小于90的课数"

    from score 

    where score < 90

    group by s_id) as a  

  inner join

  (
    select
      s_id as "学号",
      count(c_id) as "选课数"

    from score 

    group by s_id) as b

  on a.学号= b.学号
);
+--------+-----------+
| 学号   | 姓名      |
+--------+-----------+
| 0001   | 王二      |
| 0002   | 星落      |
| 0003   | 胡小适    |
+--------+-----------+
3 rows in set (0.00 sec)

小结

  • 聚合函数练习 sum, avg, count + distinct ....这些常见聚合函数的熟练使用呀.
  • group by 前的 select 不要放跟 其无关的非聚合字段, 没有意义, where 要置前, 组内过滤用 having
  • 复杂查询先理清楚逻辑, 一点点给查出来, 再拼接 Join 再过滤, 子查询等操作, 跟写代码一样的其实

原文地址:https://www.cnblogs.com/chenjieyouge/p/12609760.html

时间: 2024-11-09 03:42:18

SQL 强化练习 (五)的相关文章

SQL总结(五)存储过程

SQL总结(五)存储过程 概念 存储过程(Stored Procedure):已预编译为一个可执行过程的一个或多个SQL语句. 创建存储过程语法 CREATE proc | procedure procedure_name [{@参数数据类型} [=默认值] [output], {@参数数据类型} [=默认值] [output], .... ] as SQL_statementsgo 存储过程与SQL语句对比 优势: 1.提高性能SQL语句在创建过程时进行分析和编译. 存储过程是预编译的,在首次

SQL强化练习

SQL语句强化练习题及答案 一.简单查询 1.列出全部学生的信息. SELECT * FROM 学生 2.列出软件专业全部学生的学号及姓名. SELECT 学号,姓名 FROM 学生 WHERE 专业="软件" 3.列出所有必修课的课号. SELECT DISTINCT 课号 FROM 必修课 4.求1号课成绩大于80分的学生的学号及成绩,并按成绩由高到低列出. SELECT 学号,成绩 FROM 选课 WHERE 课号="1" AND 成绩>80 ORDER

SQL强化(一)保险业务

保险业务 : 表结构 : sql语句 : /*1. 根据投保人电话查询出投保人 姓名 身份证号 所有保单 编号 险种 缴费类型*/SELECTt2.cust_name,t2.idcard,t4.pro_id,t5.pay_type_name,t6.protype_nameFROMcontact t1, -- 联系表customer t2, -- 客户表holder t3, --product t4,pay_type t5,protype t6WHEREt1.contact_text = '159

SQL强化

保险业务 : 表结构 : sql语句 : /*1. 根据投保人电话查询出 投保人 姓名 身份证号 所有保单 编号 险种 缴费类型*/SELECT t2.cust_name, t2.idcard, t4.pro_id, t5.pay_type_name, t6.protype_nameFROM contact t1, -- 联系表 customer t2, -- 客户表 holder t3, -- product t4, pay_type t5, protype t6WHERE t1.contac

SQL基础(五):SQL函数

一.SQL Aggregate 函数: SQL Aggregate 函数计算从列中取得的值,返回一个单一的值. 1.AVG() 函数 AVG() 函数返回数值列的平均值. 语法:SELECT AVG(column_name) FROM table_name //从 "access_log" 表的 "count" 列获取平均值: SELECT AVG(count) AS CountAverage FROM access_log; //选择访问量高于平均访问量的 &qu

sql 高级 (五)(create index(创建索引) drop)

SQL create index 语句 create  index语句用于在表中创建索引. 在不读取整个表的情况下,索引使数据库应用程序可以更快地查找数据. 用户无法看到索引,它们只能被用来加速搜索/查询. 更新一个包含索引的表需要比更新一个没有索引的表更多的时间,这是由于索引本身也需要更新. 理想的做法是仅仅在常常被搜索的列(以及表)上面创建索引. 允许使用重复的值: create index  index_name ON table_name (column_name) SQL create

SQL入门经典(五) 之键和约束

这一篇博客主要讲键的创建,约束的创建.修改对象和删除对象. 主键:主键是每行的唯一标识符,必须包含唯一值(因此不能为NULL).由于主键在关系中数据库的重要性,因此它是所有键和约束中最重要的.一个表最多可以有一个主键.很少不需要主键的表.主键声明具有唯一性.常用有identity自动增长值和GUID.主键是唯一标识值.如果客户操作一个没有主键的表.连续添加2次一样数据.你怎么删除.删除总是2条一条删除.我们接着上篇博客. 下面创建一个主键表: USE panda GO --转为panda数据库操

ORACLE SQL练习(五)

--日期转换为字符串 SELECT DATE_HIRE, TO_CHAR(DATE_HIRE, 'Month dd yyyy') HIRE FROM EMPLOYEE_PAY_TBL; SELECT EMPLOYEE_TBL.EMP_ID, EMPLOYEE_TBL.LAST_NAME, EMPLOYEE_PAY_TBL.POSITION FROM EMPLOYEE_TBL, EMPLOYEE_PAY_TBL WHERE EMPLOYEE_TBL.EMP_ID = EMPLOYEE_PAY_TB

防止 jsp被sql注入的五种方法

一.SQL注入简介 SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库. 二.SQL注入攻击的总体思路 1.寻找到SQL注入的位置 2.判断服务器类型和后台数据库类型 3.针对不通的服务器和数据库特点进行SQL注入攻击 三.SQL注入攻击实例 比如在一个登录界面,要求输入用户名和密码: 可以这样输入实现免帐号登录: 用户名: ‘or 1 = 1 – 密 码: 点登陆,如若没有做特殊处理,那么这个