SQL语句汇总(终篇)—— 表联接与联接查询

上一篇博文说到相关子查询效率低下,那我们怎么能将不同表的信息一起查询出来呢?这就需要用到表联接。

和之前的UNION组合查询不同,UNION是将不同的表组合起来,也就是纵向联接,说白了就是竖着拼起来。

而表联接是通过笛卡尔乘积将表进行横向联接,所谓的通过笛卡尔乘积简单说就是两表的行依次相联再相加。要想更详细的理解可以百度下,毕竟本文主要是汇总SQL语句。
现在有两张表: t_student 和 t_class
建表语句:

CREATE TABLE `t_student` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` varchar(10) NOT NULL COMMENT '姓名',
  `age` int(3) unsigned NOT NULL COMMENT '年龄',
  `code` varchar(5) NOT NULL DEFAULT '' COMMENT '行业',
  `sex` varchar(5) NOT NULL DEFAULT '男' COMMENT '性别',
  `fk` int(11) NOT NULL DEFAULT '0' COMMENT '班级id',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
INSERT INTO `t_student` VALUES (1, '大毛', 18, '新闻', '男', 1);
INSERT INTO `t_student` VALUES (2, '王二', 20, '网络', '男', 2);
INSERT INTO `t_student` VALUES (3, '张三', 22, 'IT', '男', 3);
INSERT INTO `t_student` VALUES (4, '李四', 17, 'IT', '女', 4);
INSERT INTO `t_student` VALUES (5, '王五', 23, '财务', '男', 2);
INSERT INTO `t_student` VALUES (6, '王大雷', 21, '新闻', '男', 1);
INSERT INTO `t_student` VALUES (7, '阿迪王', 20, '网络', '男', 4);
INSERT INTO `t_student` VALUES (8, '姓王的', 24, '新闻', '男', 3);
INSERT INTO `t_student` VALUES (9, '大王', 25, 'IT', '男', 1);
INSERT INTO `t_student` VALUES (10, '大黄', 20, 'IT', '男', 4);

在这里插入图片描述

CREATE TABLE `t_class` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `code` varchar(10) NOT NULL,
  `info` int(11) NOT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `class_name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
INSERT INTO `t_class` VALUES (1, '一班', 't1', 1);
INSERT INTO `t_class` VALUES (2, '二班', 't2', 2);
INSERT INTO `t_class` VALUES (3, '三班', 't3', 3);
INSERT INTO `t_class` VALUES (4, '四班', 't4', 4);
INSERT INTO `t_class` VALUES (5, '五班', 't5', 5);

在这里插入图片描述
怎么联接这两张表呢?标准写法:

SELECT * FROM t_student JOIN t_class 

结果这里只截一小部分图,因为笛卡尔乘积后的行数等于两张表的行数乘积,实在太多了。
在这里插入图片描述

这里就可以理解表联接的原理了,依次相连再相加。当然其中很多是无效行,为了去除无效的行我们就要用到外键来进行约束。学生表中的fk与班级表中的infor相关联:

select s.*,c.name cname from t_student s JOIN t_class c on s.fk = c.info

在这里插入图片描述

这里通过外键的匹配我们就得到了一张完美的联接之后的表,它可以看做一张新表,想要任何数据均可以从此表中查询,这就是表联接的强大之处。

表联接的分类:

内联接:

内联接是指两个表中某一行相关的列值匹配时,这一行才会出现在表中。就像上例中s._fk与c._infor相同时才会出行该行,其他的行剔除。

语法为INNER JOIN 其中INNER可以省略。

内联接的简写:

select s.*,c.name cname from t_student s ,t_class c on s.fk = c.info
  • 此写法也是我们用的最多的。

外联接:

分为左外联接与右处联接。

外联接是指不管有没有匹配,被定义了外联接的表数据都要出现在结果中。比如左外联接,那么在JOIN左边的表就被定义为外联接,那么此表中所有数据都会出现在查询结果中。
注意班级表中的五班是没有学生的,所以在内联接之后理所当然的被剔除了。现在以外联接做示例:

SELECT * FROM t_student s RIGHT JOIN t_class c ON s.fk=c.info; 

在这里插入图片描述
最下面多了一行五班的信息
例如我们想查出还没有学生录入的班级信息:

SELECT c.id,c.name FROM t_student s RIGHT JOIN t_class c ON s.fk=c.info where s.id is null; 

在这里插入图片描述

这就是外联接的用法,通常用在我们想要的数据匹配不上时。

知识点罗列到这里,做题时间到:

1.查询王大雷所在的班级

select s.*,c.name cname from t_student s , t_class c where  s.fk = c.info and s.name = '王大雷'

在这里插入图片描述

2.查询同王大雷同班级的学生

select s.name from t_student s where s.fk = (select fk from t_student where name = '王大雷') and s.name != '王大雷'

在这里插入图片描述

3.查询每个班级的人数

SELECT d.cname,COUNT(d.name) FROM (SELECT ss.*,cc.name cname FROM t_class cc LEFT JOIN t_student ss ON ss.fk = cc.info) d GROUP BY d.cname;

在这里插入图片描述

4.查询班级人数最多的班级

SELECT d.cname,COUNT(d.name) count FROM (SELECT ss.*,cc.name cname FROM t_class cc LEFT JOIN t_student ss ON ss.fk = cc.info) d GROUP BY d.cname HAVING count >=ALL(SELECT COUNT(d.name) count FROM (SELECT ss.*,cc.name cname FROM t_class cc LEFT JOIN t_student ss ON ss.fk = cc.info) d GROUP BY d.cname);

在这里插入图片描述

5.查询每个班中年龄最低的人

select s.*,c.name from t_student s left join t_class c on c.info = s.fk where s.age <= (select min(age) from t_student )

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/u012620150/article/details/84029544