SQL 强化练习(三)

继续来练习 sql 查询, 似乎也没有什么窍门, 跟着写多了, 自然就记住了, 这个帖子, 来记录一波, 模糊查询 like; 四表关联查询: 老师名 -> 老师id -> 课程id -. 学生 id -> 学生表

表关系

需求01

查询姓 “王” 的学生个数;

查询姓名中包含 "王" 的学生信息;

查询姓名为 3个字的学生姓名和性别;

查询姓张的老师中, 不重名的老师个数;

分析

主要是关于模糊查询这块, 在 mysql 中, 即关于关键字 “like" 和 通配符 ”%, - “ 等的应用。

select
	count(s_id) as 老师人数
from student
where
  s_name like "王%";

+--------------+
| 老师人数     |
+--------------+
|            1 |
+--------------+
1 row in set (0.00 sec)

-- % 匹配任意
select  *
from student
where s_name like "%王%";

+------+--------+------------+--------+
| s_id | s_name | birth_date | gender |
+------+--------+------------+--------+
| 0001 | 王二   | 1989-01-01 | 男     |
+------+--------+------------+--------+
1 row in set (0.00 sec)
-- "_" 下划线表示匹配单个字符
select
  s_name,
  gender
from student
where s_name like "___";
+-----------+--------+
| s_name    | gender |
+-----------+--------+
| 胡小适    | 男     |
+-----------+--------+
1 row in set (0.00 sec)
-- distinct 去重
select
	count(distinct  s_name) as "王姓不重名老师数"
from student
where s_name like "王%";

+--------------------------+
| 王姓不重名老师数         |
+--------------------------+
|                        1 |
+--------------------------+
1 row in set (0.00 sec)

需求02

查询没有选过 "仲尼" 老师课的学生的学号, 姓名, 性别.

分析

涉及 教师表, 课程表, 成绩表, 学生表 . 一步步查出来即可

面向过程

先根据老师 "姓名" -> 老师 id -> 课程 id -> 选课 score 拿到 学生 id -> 学生表信息

a. 通过老师姓名 "仲尼" 从 教师表 拿 "教师id"

select
	t_id
from teacher
where t_name = "仲尼";
+------+
| t_id |
+------+
| 0002 |
+------+
1 row in set (0.00 sec)

b. 通过 "教师id" 从 课程表 拿到 "课程id"

select
  c_id
from course
where
	t_id = (

		select
			t_id
		from teacher
		where t_name = "仲尼"
		);

+------+
| c_id |
+------+
| 0001 |
+------+

c. 通过 "课程id" 从 成绩表 拿到 "学生id" (课程: 学生 是 1:n)

select
  s_id
from score
where c_id = (

	select
	  c_id
	from course
	where
		t_id = (

			select
				t_id
			from teacher
			where t_name = "仲尼"
			)
	);

+------+
| s_id |
+------+
| 0001 |
| 0003 |
+------+

d. 通过 "学生id" 从 学生表 拿到 学生的学号, 姓名, 性别 (没选 就 not in )

-- 没有选就 not in
select
  s_id as "学号",
  s_name as "姓名",
  gender as "性别"
from student
where s_id not in (

	select
	  s_id
	from score
	where c_id = (

		select
		  c_id
		from course
		where
			t_id = (

				select
					t_id
				from teacher
				where t_name = "仲尼"
				)
		)
);

+--------+--------+--------+
| 学号   | 姓名   | 性别   |
+--------+--------+--------+
| 0002   | 星落   | 女     |
| 0004   | 油哥   | 男     |
+--------+--------+--------+
2 rows in set (0.00 sec)

这种思路, 感觉跟咱变成用的, 面向过程是一样的思维, 比较注重逻辑关系. 我个人是比较喜欢的, 逻辑性和推理是我一直比较感兴趣的话题, 尤其是数学公式推到, 我觉得非常的有意思. 当然这里我能写出这个一步步的逻辑呢, 主要还是基于对表字段的熟悉和其关联关系, 表关系 (1:1, 1:n, n:n )等的掌握, 这里逻辑, 即:

老师姓名 -> 老师id -> 课程 id -> 学生id -> 学生信息

tips: 成绩表中, 学生 与 选课 是 1: n 的关系哦

但业务中, 往往对表字段, 关联不那么熟悉 , 说业务嘛, 了解业务就已经是非常头疼的事情了, 还有一个表字段有很多啥的, 搞起来则麻烦对于理解这些逻辑关联关系.

连接查询写法

思路还是一样的, 差别就是, 我个人感觉, 这是一种 "面向对象" 的写法 , 当然不是咱真正的面向对象, 就是 表拼接 .

分析

关键是在于 "选课" 这张表, 即成绩表, 它的字段有:

学号, 课程号, 课程名称, 成绩

有了 "课程号" 不就知道了 "教师id" 和 "教师姓名" 了吗 (left join 或 inner join 都行)

学号, 课程号, 课程名称, 成绩; 教师id, 教师姓名

最后, 根据 "学号" 不就知道学生信息了嘛 (inner join)

学名, 姓名,性别;学号, 课程号, 课程名称, 成绩; 教师id, 教师姓名
-- 注意别名的使用

select
  s.*,
  c.*,
  t.*

from score as s

-- 成绩表 关联 课程表
inner join course as c
on
  s.c_id = c.c_id 

-- 课程表 关联 教师表
inner join teacher as t
on
  c.t_id = t.t_id

where
  t.t_name = "仲尼";

+------+------+-------+------+--------+------+------+--------+
| s_id | c_id | score | c_id | c_name | t_id | t_id | t_name |
+------+------+-------+------+--------+------+------+--------+
| 0001 | 0001 |    80 | 0001 | 语文   | 0002 | 0002 | 仲尼   |
| 0003 | 0001 |    80 | 0001 | 语文   | 0002 | 0002 | 仲尼   |
+------+------+-------+------+--------+------+------+--------+

其实 , 咱只要用到 s_id 就可以了, 以 s_id 作为条件 去查出相应的 学生信息即可

select
  s_id,
  s_name,
  gender
from student
where
  s_id not in (

	select
	  s.s_id

	from score as s

	-- 成绩表 关联 课程表
	inner join course as c
	on
	  s.c_id = c.c_id 

	-- 课程表 关联 教师表
	inner join teacher as t
	on
	  c.t_id = t.t_id

	where
	  t.t_name = "仲尼"

	);

+------+--------+--------+
| s_id | s_name | gender |
+------+--------+--------+
| 0002 | 星落   | 女     |
| 0004 | 油哥   | 男     |
+------+--------+--------+
2 rows in set (0.00 sec)

表关联查询的这种方式, 我在真是的业务中是用的蛮多的, 毕竟我去了解每个表的字段, 逻辑什么的还是比较麻烦的, 一个表的字段是很多的, 我通常就给他们都拼接起来一张大表, 然后再筛选. 核心还是在思考这3个核心的问题:

  • 涉及 哪几张表 和 相关的字段大概有哪些?
  • 表之间的关键 KEY 是什么?
  • 表与表的关系 (1:1; 1:n , n:n)

小结

  • 模糊查询 like 的使用
  • 多表关联查询, 可以面向过程, 和类似面向对象的方式 (逻辑, 表连接)

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

时间: 2024-10-28 23:11:14

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

防止sql注入的三种方法

常用的避免SQL注入的三种方法 一,存储过程 在学习数据库视频的时候接触过,它是存储在数据库中的一些事先编译好的指令.在用的时候不用重新编写,直接调用就好了.所以,使用它可以大大提高程序的执行效率. 那么,如果创建一个存储程序并使用它呢?这是我们今天要解决的问题 1.创建过程 可编程性--下拉菜单--存储过程--右键--查询菜单--指定模板参数的值--新建查询--输入语句--查询菜单中的分析检查语法是否正确--执行 2.具体创建语法 在创建存储程序时,为了应对各种变换的数据,通常会涉及到带参数的

SQL Server之 (三) 分组 类型转换函数 插入多条数据 字符串函数

SQL Server之 (三)  分组 类型转换函数  插入多条数据  字符串函数 自己学习笔记,转载请注明出处,谢谢!---酸菜 1.SQL 数据分组----Group by /Having  ①有一学生信息表:StuID/StuName/StuAge/StuGender/StuClassID; 求每个班级的ID和对应人数:select StuClassID 班级ID,count(*) 班级人数  from StuInfo group by StuClassID ; 求所有同学中男女同学对应人

SQL总结(三)其他查询

SQL总结(三)其他查询 其他常用的SQL,在这里集合. 1.SELECT INTO 从一个表中选取数据,然后把数据插入另一个表中.常用于创建表的备份或者用于对记录进行存档. 语法: SELECT column_name(s) INTO new_table_name [IN externaldatabase] FROM old_tablename IN 子句可用于向另一个数据库中拷贝表. 1)备份表信息 SELECT ID,Name INTO Students_Backup FROM Stude

sql调用最近三天发布的文章

<?php$ltime=time()-86400*3;?>{pc:get sql="select * FROM  v9_news where inputtime>$ltime order by id desc"  num="13" page="$page" return="data"}{loop $data $n $r}<li><a target="_blank" hre

PDO中执行SQL语句的三种方法

在PDO中,我们可以使用三种方式来执行SQL语句,分别是 exec()方法,query方法,以及预处理语句prepare()和execute()方法~大理石构件来图加工 在上一篇文章<使用PDO构造函数连接数据库及DSN详解>中,我们介绍了如何使用构造函数连接数据库和DSN的详解,那么我们这篇文章跟大家介绍在PDO中执行SQL语句的三种方式,下面我们将一一介绍! 第一种方法:exec()方法 exec()方法返回执行SQL 语句后受影响的行数,其语法格式如下: 1 int PDO::exec(

SQL强化练习

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

SQL语句汇总(三)——聚合函数、分组、子查询及组合查询 - Darly

–COUNT:统计行数量 –SUM:获取单个列的合计值 –AVG:计算某个列的平均值 –MAX:计算列的最大值 –MIN:计算列的最小值 首先,创建数据表如下: 执行列.行计数(count): 标准格式 SELECT COUNT(<计数规范>) FROM <表名> 其中,计数规范包括: - * :计数所有选择的行,包括NULL值: - ALL 列名:计数指定列的所有非空值行,如果不写,默认为ALL: - DISTINCT 列名:计数指定列的唯一非空值行. 例,计算班里共有多少学生:

PL/SQL 编程(三 )程序包和包体,触发器,视图,索引

一.程序包和包体 程序包(package):存储在数据库中的一组子程序.变量定义.在包中的子程序可以被其它程序包或子程序调用.但如果声明的是局部子程序,则只能在定义该局部子程序的块中调用该局部子程序. 它具有面向对象程序设计语言的特点,是对这些PL/SQL 程序设计元素的封装.包类似于JAVA语言中的类,其中变量相当于类中的成员变量,过程和函数相当于类方法. create or replace package stuinfo as type stucur is ref cursor; proce

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