数据库学习之MySQL (十三)——多表查询 SQL92 SQL99 连接种类划分

文章目录

    • 多表问题
    • 案例
    • 笛卡尔乘积
    • 添加 连接条件
    • 连接的种类划分 SQL92 99标准
    • 彩蛋1 内连接与外连接的区别
    • 彩蛋2 笛卡尔乘积结果有啥用
    • 预告

多表问题

前面1~12节我们学习了单个表的理解,以及各种查询的语句,
但是,实际应用中很可能是多表,
就比如我想做一个新型肺炎疫情的数据表,包含每个省确诊人数,死亡人数等栏目(列 属性)。那么每个省都需要一个表,等我需要后端调数据库的时候,总得把表联动,一起查询一波(比我想知道所有省加起来的总和以得到全国的数据 可以少爬一个网站)
总之就是,多表查询是实际运用中必不可少的。
我们先保存下面代码,然后在SQLyog执行一波:

/*
SQLyog Ultimate v10.00 Beta1
MySQL - 5.7.18-log : Database - data2
*********************************************************************
*/


/*!40101 SET NAMES utf8 */;

/*!40101 SET SQL_MODE=''*/;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`data2` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `data2`;

/*Table structure for table `admin` */

DROP TABLE IF EXISTS `admin`;

CREATE TABLE `admin` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(10) NOT NULL,
  `password` varchar(10) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

/*Data for the table `admin` */

insert  into `admin`(`id`,`username`,`password`) values (1,'john','8888'),(2,'lyt','6666');

/*Table structure for table `beauty` */

DROP TABLE IF EXISTS `beauty`;

CREATE TABLE `beauty` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `sex` char(1) DEFAULT '女',
  `borndate` datetime DEFAULT '1987-01-01 00:00:00',
  `phone` varchar(11) NOT NULL,
  `photo` blob,
  `boyfriend_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;

/*Data for the table `beauty` */

insert  into `beauty`(`id`,`name`,`sex`,`borndate`,`phone`,`photo`,`boyfriend_id`) values (1,'柳岩','女','1988-02-03 00:00:00','18209876577',NULL,8),(2,'苍老师','女','1987-12-30 00:00:00','18219876577',NULL,9),(3,'Angelababy','女','1989-02-03 00:00:00','18209876567',NULL,3),(4,'热巴','女','1993-02-03 00:00:00','18209876579',NULL,2),(5,'周冬雨','女','1992-02-03 00:00:00','18209179577',NULL,9),(6,'周芷若','女','1988-02-03 00:00:00','18209876577',NULL,1),(7,'岳灵珊','女','1987-12-30 00:00:00','18219876577',NULL,9),(8,'小昭','女','1989-02-03 00:00:00','18209876567',NULL,1),(9,'双儿','女','1993-02-03 00:00:00','18209876579',NULL,9),(10,'王语嫣','女','1992-02-03 00:00:00','18209179577',NULL,4),(11,'夏雪','女','1993-02-03 00:00:00','18209876579',NULL,9),(12,'赵敏','女','1992-02-03 00:00:00','18209179577',NULL,1);

/*Table structure for table `boys` */

DROP TABLE IF EXISTS `boys`;

CREATE TABLE `boys` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `boyName` varchar(20) DEFAULT NULL,
  `userCP` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

/*Data for the table `boys` */

insert  into `boys`(`id`,`boyName`,`userCP`) values (1,'张无忌',100),(2,'鹿晗',800),(3,'黄晓明',50),(4,'段誉',300);

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

执行完SQL语句,我们拥有了data2这个数据库

案例

现在
我们有个问题:下面这两张表,让id相同的男神和女神在一起(一行排列)该怎么办?不限定显示的栏目(列 属性)
数据库学习之MySQL (十三)——多表查询 SQL92 SQL99 连接种类划分_第1张图片
数据库学习之MySQL (十三)——多表查询 SQL92 SQL99 连接种类划分_第2张图片
很明显正确答案应该是只有4行,柳岩 - 张无忌 苍老师 - 鹿晗 这样的etc
我们该怎么实现?
一开始想 SQL应该会很智能:我这么写:

SELECT * FROM `beauty`,`boys` 

应该会正确匹配吧?

笛卡尔乘积

然后结果是:
数据库学习之MySQL (十三)——多表查询 SQL92 SQL99 连接种类划分_第3张图片

发现出来了48行,也就是女神的12行 * 男神的 4行 = 48行
这就是著名的笛卡尔乘积现象(Cartesian product)
那怎么处理呢?

添加 连接条件

废话不说 看代码:

USE data2;
SELECT `name`,`boyname` FROM `beauty`,`boys`
WHERE beauty.`id` = boys.`id`;

数据库学习之MySQL (十三)——多表查询 SQL92 SQL99 连接种类划分_第4张图片
注意两个问题:
1 利用WHERE 添加连接条件
2 同名不同表的属性用点符号访问表对象区分
这里的语法非常契合对象语法,
把表做对象类,
列做属性,
行做类实例,
我们就是对每个实例进行操作,
判断方式就是通过每个类的属性(连接条件)

所以现在来自由发挥一下 比如 将女神的boyfriend_id 与男神的id进行匹配:
数据库学习之MySQL (十三)——多表查询 SQL92 SQL99 连接种类划分_第5张图片

USE data2;
SELECT `name`,`boyname` FROM `beauty`,`boys`
WHERE beauty.`boyfriend_id` = boys.`id`;

其实就更改了连接条件

连接的种类划分 SQL92 99标准

我们刚刚做的都是简单的条件 那么有更加复杂的呢?这时我们先剧透分类一波,算是纲举目张:
总共分为三类:内连接外连接以及交叉连接
内连接就是我们刚刚用的,包含等值连接非等值连接以及自连接
外连接包含左外连接 右外连接全外连接
交叉连接没有子项。

这些都是基于SQL的标准的,有老的1992年颁布的92标准和1999颁布的的99标准,由于99是基于92的,大体差不多,我们作为了解学一下92标准,之后重点学习99标准。
92对MySQL支持仅限于内连接
具体语法将在下一节全部介绍完毕。

彩蛋1 内连接与外连接的区别

比较灵活的朋友可能发现一个问题:
前面案例中,有些女神的boyfriend_id 男朋友号不在1~4范围内
男生的id 却只是1~4 我们想让

beauty.`boyfriend_id` = boys.`id`; 

所以联合起来的表 仅仅只有四行 这看起来挺智能的 把没有匹配的所有可能滤除了

但是 如果我想做的是基于女神的表呢?
就是有12行,
男朋友找不到就空着嘛2333
其他信息比如电话号码必须有:)
这样就要用到所谓了外连接 也就是 一张表匹配另一张表 是不完全的 可能一个多一个少(比如这里 女神表多 男生少)
内连接则是 完全匹配的 也就 通过女神的男朋友id 都能找到对应的男生

不用担心这里不懂 我们后面会再次说明 传送:
数据库学习之MySQL (十六)—— SQL99 外连接 左外连接 右外连接 全外连接

彩蛋2 笛卡尔乘积结果有啥用

我们之前用错误的代码得到的笛卡尔乘积 其实是个TEMP 暂时的 虚拟的 结果集
也就是 我们连接条件 筛选, 就是从笛卡尔乘积结果 进行筛选的
而笛卡尔乘积结果是从From语句表中得到的

至于筛选条件WHERE 又可能是从连接条件的结果筛选得来的
一环扣一环

预告

那么,接下来下一节,我们来进行92标准的 内连接的学习,包含等值连接 非等值连接 自连接
数据库学习之MySQL (十四)—— 92标准的 非等值连接 自连接

  • 本文专栏
    MySQL专栏
  • 我的其他专栏 希望能够帮到你 ( •̀ ω •́ )✧
    • 手把手带你学后端(服务端)
    • python这么火 想要深入学习python 玩一下简单的应用嘛?
      python应用
  • 谢谢大佬支持! 萌新有礼了:)

你可能感兴趣的:(MySQL)