首页 » 网站建设 » phpcase多个前提技巧_2周零根本搞定SQL多表查询

phpcase多个前提技巧_2周零根本搞定SQL多表查询

访客 2024-11-18 0

扫一扫用手机浏览

文章目录 [+]

在上一篇文章里,我们学习了SQL的繁芜查询,但是依然只是针对一个表的,但在实际事情中,我们须要的数据,每每分布在多个表中,所以为了更好的办理事情中的实际问题,本日我们一起来学习如何用SQL进行多表查询吧!

1.表的加法

在之前的学习中,我们建了一张表course,大家还记得吗?

phpcase多个前提技巧_2周零根本搞定SQL多表查询

接下来我们再数据库中再添加一张表course1,如下:

phpcase多个前提技巧_2周零根本搞定SQL多表查询
(图片来自网络侵删)

如果大家忘却了如何新建表并向表中插入数据,就回到何书365:轻松搞天命据剖析之MySQL——零根本入门里面再复习一下吧!

当然你也可以按如下步骤操作来添加course1:

右键,复制表,构造和数据,得到复制的表course_copy

重命名,将表名course_copy重命名为course1

右键,打开表,对数据进行修正并保存。

添加完course1这张表,现在在school数据库中,我们就有了两张关于课程信息的表。
大家可以看到course和course1这两张表的构造是一样的,不同的是两张表内在图片红框标出的地方存放的数据是不一样的。

下面,我们用这两张表来学习表的加法,来把这两张表中的数据组合在一起。
表的加法,我们要用UNION来实现。

UNION的浸染 UNION运算符用于组合两个或更多SELECT语句的结果集。

UNION利用条件UNION中的每个SELECT语句必须具有相同的列数

这些列也必须具有相似的数据类型每个SELECT语句中的列也必须以相同的顺序排列

UNION 语法

SELECT column_name(s) FROM table1UNIONSELECT column_name(s) FROM table2;

下面,我们以上面两张课程表为栗子,看一下union的用法:

SELECT 课程号,课程名称from courseUNIONselect 课程号,课程名称FROM course1;

从结果表中可以看到,course和course1两张表中不同的数据合并在一起了(红框内的数据),而且绿框中为两张表中重复的数据,SQL会把重复值删除,只保留一个值。

如果许可重复值,请利用 UNION ALL。

UNION ALL 语法

SELECT column_name(s) FROM table1UNION ALLSELECT column_name(s) FROM table2;

※ 注:UNION结果集中的列名总是即是UNION中第一个SELECT语句中的列名。

SELECT 课程号,课程名称from courseUNION ALLselect 课程号,课程名称FROM course1;

如结果所示,两个表中的共有的数据“0001,语文”的重复数据都被保留下来了。

总结:

UNION便是将多段功能类似的SQL连接起来,并且可以去掉重复的行,有DISTINCT的功能。
UNION ALL则只是纯挚的将多段类似SQL连接起来而且。
他们的好处是可以将繁芜SQL按不同的功能或浸染拆分成一小段SQL进行拼接,可以有效提高查询效率。
2.表的联结

学习完了表的加法,接下来我们来学习表的联结。

关系型数据库是由多张表组成的,如下图,即为school数据库中的四张表:

看到这四张表,你能创造他们之间有什么关系吗?

还记得我们在之前的文章里面学习的主键的观点吗?我们来看student表和score表两表之间的关系,两张表便是通过学号这个主键关联起来的。
为了更清楚的表现这两张表的关系,图片里我用相同颜色将同一个学生的信息框选起来。

如果我想知道学号为0001的学生的成绩是多少,我就可以在score表中查找到学号为0001的学生的课程号和成绩(一共有3行数据)。
以是关系便是表之间可以根据主键进行对应的匹配,在关系型数据库中,这种关系的学名叫做联结(join)。

school数据库中四张表联结关系图

JOIN连接的浸染

JOIN 连接用于把来自两个或多个表的行结合起来,基于这些表之间的共同字段。

不同的 JOIN

在我们连续讲解实例之前,我们先列出可以利用的不同的 SQL JOIN 类型:

CROSS JOIN(交叉联结):没有条件的join,返回被连接的两个表所有数据行的笛卡尔积;INNER JOIN(内联结):如果表中有至少一个匹配,则返回行;LEFT JOIN(左联结):纵然右表中没有匹配,也从左表返回所有的行;RIGHT JOIN(右联结):纵然左表中没有匹配,也从右表返回所有的行;FULL JOIN(全联结):只要个中一个表中存在匹配,则返回行。

CROSS JOIN(交叉联结)

图片来源于猴子老师:《从零学会SQL》系列课程

返回到的数据行数即是第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。

SELECT FROM A CROSS JOIN B

交叉联结在实际事情中利用的比较少,由于返回的结果行数太多了,表太大,打算量大,效率非常低,不建议利用。
但交叉联结是所有联结的根本,接下来学习的几种联结都是在交叉联结的根本上加了特定的条件。

INNER JOIN(内联结)

从多个表中返回知足 JOIN 条件的所有行,语法如下

SELECT column_name(s)FROM table1INNER JOIN table2 ON table1.column_name = table2.column_name;

举颗栗子:

对付这两个表,内联结便是查找出同时存在与这两张表中的数据(绿框中数据),并返回所有行,红框中数据在score表中没有,则不返回。

SELECT a.学号,a.姓名,b.课程号,b.成绩 -- 3 取出表a的学号、姓名列,取出b表的课程号、成绩两列。
from student as a INNER JOIN score AS b -- 1 同时利用两张表,并重命名ona.学号=b.学号; -- 2 两个表的联结条件

LEFT JOIN(左联结)

SQL左链接LEFT JOIN关键字返回左表(表1)中的所有行,纵然在右表(表2)中没有匹配。
如果在精确的表中没有匹配,结果是NULL。

SELECT column_name(s)FROM table1LEFT JOIN table2ON table1.column_name=table2.column_name;

或(在一些数据库中,LEFT JOIN称为LEFT OUTER JOIN)

SELECT column_name(s)FROM table1LEFT OUTER JOIN table2ON table1.column_name=table2.column_name;

栗子:

查询学生表中所有学生的课程号和成绩

SELECT a.学号,a.姓名,b.课程号,b.成绩from student as a LEFT JOIN score AS bONa.学号=b.学号;

我们创造“0004,王思聪”没有对应的课程号和成绩,是由于他们没有在score表中存在,没有匹配上他们的信息。
但是由于是左连接,就把主表student的信息全部显示出来了,便是对应上图的table1。

那么我们如何实现下图的效果呢?也便是如何在左联结的根本之上去掉两个表中共同的部分。

很大略,便是在上面的根本上添加一个where子句,来筛选出表2中没有匹配的信息,再返回主表信息。

SELECT a.学号,a.姓名,b.课程号,b.成绩from student as a LEFT JOIN score AS bONa.学号=b.学号WHERE b.学号 is NULL;

RIGHT JOIN(右联结)

SQL右链接 RIGHT JOIN 关键字返回右表(table2)的所有行,纵然在左表(table1)上没有匹配。
如果左表没有匹配,则结果为NULL。

SELECT column_name(s) FROM table1RIGHT JOIN table2 ON table1.column_name = table2.column_name;

在一些数据库中,RIGHT JOIN 称为 RIGHT OUTER JOIN。

右连接与左连接的主表刚好相反,会将table2中的数据完备显示,如果table1中没有匹配上的就不显示。

这里我们就不举栗子啦。
那么你可能会问旁边联结有何差异呢?又如何选择呢?

右联结和左联结实质上是相同的,只是指定的主表会有所差别,究竟是左联结还是右联结该当根据实际需求来决定,作为主表,须要做到的是,要覆盖所有查询主体(什么是查询主体,比如,我们要查询所有学生的成绩,课程号,.......,这个里面的主体便是学生),如果各表覆盖的主体个数没有差异,旁边联结和内联结没有差异。

普通的讲,便是选哪个为主表,就用什么联结:

left以 left join 左侧的表为主表right 以 right join 右侧表为主表inner join 查找的数据是旁边两张表共有的。

FULL JOIN(全联结)

当左(表1)或右(表2)表记录匹配时,FULL OUTER JOIN关键字将返回所有记录。
把稳: FULL OUTER JOIN可能会返回非常大的结果集!
且MySQL不支持全联结。
但可以通过union来实现。

SELECT column_name(s) FROM table1FULL OUTER JOIN table2 ON table1.column_name = table2.column_name;mysql> select from A left join B on B.name = A.name -> union -> select from A right join B on B.name = A.name;

全连接便是将table1和table2的内容完备显示,不管有没有匹配上。

好啦,到这里,SQL的所有联结就讲完啦!
是不是有点方?不怕!
下面一张图,我们把前面学的联结来一个总结:

忘的时候看一看,SQL联结So easy!

JOIN在SQL中霸占主要的地位,通过JOIN我们可以将有匹配关系的两张表或更多表进行关联,来获取我们想要的数据。
关联的办法也比较灵巧,常用的便是INNER JOIN,请务必节制它。
接下来,我们就来学甚至用吧!

3.联结运用案例

在开始案例实操之前再回顾一下用SQL办理业务问题的步骤,时候服膺,不要忘了哦!

a).把业务问题解读成普通易懂的大口语;

b).写出剖析思路(按步骤分解);

c).写出对应的SQL子句。

栗子1:查询所有学生的学号、姓名、选课数、总成绩。

a).把业务问题解读成普通易懂的大口语:

查询学生的学号、姓名,对每个学生所选的课程号计数,并对每个学生的成绩求和。

b).写出剖析思路(按步骤分解):

提取关键字:学号,姓名,选课数,总成绩学生姓名、学号——>student表选课数——>每个学生的选课数:score表,按学号分组group by,并对课程号计数count总成绩——>每个学生的总成绩:score表,按学号分组group by,并对成绩求和sum学生是查询主体,student 和score表通过学号联结,且为左联结。

c).写出对应的SQL子句:

SELECT s1.学号,s1.姓名,count(课程号) as 选课数,SUM(成绩) as 总成绩from student as s1 LEFT JOIN score AS s2ONs1.学号=s2.学号GROUP BY s1.学号;

栗子2:查询均匀成绩大于85的所有学生的学号,姓名和均匀成绩

a).把业务问题解读成普通易懂的大口语:

查询学生的学号、姓名、均匀成绩,对每个学生的成绩求均匀值,并选出大于85的数据。

b).写出剖析思路(按步骤分解):

提取关键字:学号,姓名,均匀成绩学生姓名、学号——>student表均匀成绩——>每个学生的均匀成绩:score表,按学号分组group by,并求对成绩求均匀值avg学生是查询主体,student 和score表通过学号联结,且为左联结。

c).写出对应的SQL子句:

SELECT s1.学号,s1.姓名,AVG(s2.成绩) as 均匀成绩from student as s1 LEFT JOIN score AS s2ONs1.学号=s2.学号GROUP BY s1.学号HAVING 均匀成绩>85;

栗子3:查询学生的选课情形:学号,姓名,课程号,课程名称

a).把业务问题解读成普通易懂的大口语:

查询学生的学号、姓名、课程号,课程名称。

b).写出剖析思路(按步骤分解):

提取关键字:学号、姓名、课程号,课程名称学生姓名、学号——>student表课程号,课程名称——>course表课程号——>引入score表。
由于student表和course表没有共同关键字,无法产生联结。
学生是查询主体,student 和score表通过学号左联结,score表和course表通过课程号左联结。

c).写出对应的SQL子句:

SELECT s1.学号,s1.姓名,c1.课程号,c1.课程名称from student as s1 LEFT JOIN score AS s2ONs1.学号=s2.学号LEFT JOIN course as c1ONs2.课程号=c1.课程号;

这三颗栗子都是非常常见的口试题,宝宝们一定要亲自操作一遍哦!
完成后,我们连续学习!

4.case表达式

SQL中的case表达式的浸染是用来对“某个变量”进行某种转化,利用case可以实现不同条件的统计。

case表达式很像我们的if else的浸染,在创造为真的WHEN子句时,CASE表达式的真假值判断就会中止,实行then语句中的命令,而剩余的WHEN子句会被忽略。
如果所有的WHEN子句都为假值,则实行else子句。

CASE具有两种格式,大略CASE函数和CASE搜索函数。
这两种办法,大部分情形下可以实现相同的功能。

大略case函数

CASE column WHEN <condition> THEN value WHEN <condition> THEN value......ELSE value END

CASE搜索函数

CASE WHEN <condition> [,<condition>] THEN value WHEN <condition> [,<condition>] THEN value......ELSE valueEND

须要把稳的是:

else这句非必须但最好带上,如果when中没有符合条件的,且有没有else掌握,那么,这样的case会返回null,null不是个好东西,以是你一定要只管即便掌握减少返回null的情形;

end子句不可以省略不写;

大略点说,在能写列名和常量的地方,都可以写 CASE 表达式,由于它返回的是一个标量值,常日我们在select子句中利用。

这么提及来貌似有点抽象,我们还是上栗子吧!

栗子1:判断学生的成绩是否及格(>=60及格,<60不及格)

SELECT 学号,课程号,成绩,(CASE when 成绩>=60 then '及格' when 成绩<60 then '不及格' else NULLend ) as 是否及格from score;

上面的case语句实行逻辑:若第一个WHEN子句为真,则CASE表达式的真假值判断就会中止,实行then语句中的命令,而剩余的WHEN子句会被忽略。
若第一个WHEN子句为假值,则实行第二个WHEN子句,以此类推。
如果所有的WHEN子句均为假值,则实行ELSE子句。

栗子2:查询出每门课程的及格人数和不及格人数

SELECT 课程号,SUM(CASE when 成绩>=60 then 1 else 0end) as 及格人数,SUM(CASE when 成绩<60 then 1 else 0end)as 不及格人数from scoreGROUP BY 课程号;

先运行group by对数据进行分组,再运行case表达式,得到每一行的及格人数:如果这一行的成绩>=60,就将这一行的及格人数值设置为1,否则则设置为0。
表示这一行及格人数为1,不及格人数为0;末了通过sum函数,对及格人数进行求和,同理可得不及格人数。

栗子3:利用分段{100-85}、{85-70},{70-60},{<60}来统计各科成绩,根据课程号、课程名称统计各分段人数。

a).把业务问题解读成普通易懂的大口语:

按课程号和课程名称分组,统计成绩在{100-85}、{85-70},{70-60},{<60}的分别有多少人。

b).写出剖析思路(按步骤分解):

提取关键字:课程号、课程名称、各分段成绩课程号,课程名称——>course表课程号、成绩——>score表课程(课程号、课程名称)是查询主体,course表和score表通过课程号左联结(这里设定course表在左,为主表,所以是左联结。
旁边是相对付主表的观点,灵巧选择即可)。
成绩分为{100-85}、{85-70},{70-60},{<60}几个区间,为针对详细行数据(记录)的非常规分组,利用case语句。
各科成绩——>根据课程号/课程名称进行常规分组,group by语句。

c).写出对应的SQL子句:

SELECT s1.课程号,c1.课程名称,sum(case when 成绩 between 85 and 100 then 1else 0end ) as '{100,85}',sum(case when 成绩 between 70 and 85 then 1else 0end ) as '{85,70}',sum(case when 成绩 between 60 and 70 then 1else 0end ) as '{70,60}',sum(case when 成绩 < 60 then 1else 0end ) as '{<60}'from course as c1 LEFT JOIN score as s1ONc1.课程号=s1.课程号GROUP BY s1.课程号,c1.课程名称;

这里面须要把稳的是凡是在group by后面涌现的字段,必须同时在select后面涌现;凡是在select后面涌现的、同时未在聚合函数中涌现的字段,必须同时涌如今group by后面。

由于查询的结果哀求有课程名称,以是group by中也要加上课程名称。
group by里面加上课程名称的条件是不影响分构成果。
这里面课程号和课程名称是逐一对应的,以是group by子句中添加课程名称对分构成果是没有影响的。
由于对付group by 子句,当用多个列来分组时,这几个列的值全部相同才算一组。

总结:CASE是我们在日常事情中利用非常频繁的一个功能,可以很好的将我们须要的数据单独的显示在一列里面,有助于对数据有个比较清晰的节制。
与Excel的转置有点类似,但是其功能的多样性又比Excel更强一点。

好啦,到这里,本日的学习内容就全部结束啦!
关于多表查询你节制了多少?接下来,例行的饭后甜点又来啦!

SQLzoo练习

欢迎来到SQLZOO开始本日的练习:https://sqlzoo.net/

好啦,本日的内容就学到这里啦!
末了依然是一张思维导图帮助你搭建知识体系:

祝你早安,午安,晚安!
See you next time!

标签:

相关文章

phpini变量技巧_PHP 内存泄漏分析定位

场景二 程序操作大数据时产生拷贝场景三 配置不合理系统资源耗尽场景四 无用的数据未及时开释深入理解php内存管理php-fpm内存...

网站建设 2024-12-12 阅读0 评论0

php轮回说话技巧_PHP 轮回While 轮回

PHP 循环在您编写代码时,您常常须要让相同的代码块一次又一次地重复运行。我们可以在代码中利用循环语句来完成这个任务。在 PHP...

网站建设 2024-12-12 阅读0 评论0