前面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相同的男神和女神在一起(一行排列)该怎么办?不限定显示的栏目(列 属性)
很明显正确答案应该是只有4行,柳岩 - 张无忌 苍老师 - 鹿晗 这样的etc
我们该怎么实现?
一开始想 SQL应该会很智能:我这么写:
SELECT * FROM `beauty`,`boys`
应该会正确匹配吧?
发现出来了48行,也就是女神的12行 * 男神的 4行 = 48行
这就是著名的笛卡尔乘积现象(Cartesian product)。
那怎么处理呢?
废话不说 看代码:
USE data2;
SELECT `name`,`boyname` FROM `beauty`,`boys`
WHERE beauty.`id` = boys.`id`;
注意两个问题:
1 利用WHERE 添加连接条件
2 同名不同表的属性用点符号访问表对象区分
这里的语法非常契合对象语法,
把表做对象类,
列做属性,
行做类实例,
我们就是对每个实例进行操作,
判断方式就是通过每个类的属性(连接条件)
所以现在来自由发挥一下 比如 将女神的boyfriend_id 与男神的id进行匹配:
USE data2;
SELECT `name`,`boyname` FROM `beauty`,`boys`
WHERE beauty.`boyfriend_id` = boys.`id`;
其实就更改了连接条件
我们刚刚做的都是简单的条件 那么有更加复杂的呢?这时我们先剧透分类一波,算是纲举目张:
总共分为三类:内连接,外连接以及交叉连接
内连接就是我们刚刚用的,包含等值连接、非等值连接以及自连接
外连接包含左外连接 右外连接 和 全外连接
交叉连接没有子项。
这些都是基于SQL的标准的,有老的1992年颁布的92标准和1999颁布的的99标准,由于99是基于92的,大体差不多,我们作为了解先学一下92标准,之后重点学习99标准。
92对MySQL支持仅限于内连接
具体语法将在下一节全部介绍完毕。
比较灵活的朋友可能发现一个问题:
前面案例中,有些女神的boyfriend_id 男朋友号不在1~4范围内
男生的id 却只是1~4 我们想让
beauty.`boyfriend_id` = boys.`id`;
所以联合起来的表 仅仅只有四行 这看起来挺智能的 把没有匹配的所有可能滤除了
但是 如果我想做的是基于女神的表呢?
就是有12行,
男朋友找不到就空着嘛2333
其他信息比如电话号码必须有:)
这样就要用到所谓了外连接 也就是 一张表匹配另一张表 是不完全的 可能一个多一个少(比如这里 女神表多 男生少)
那内连接则是 完全匹配的 也就 通过女神的男朋友id 都能找到对应的男生
不用担心这里不懂 我们后面会再次说明 传送:
数据库学习之MySQL (十六)—— SQL99 外连接 左外连接 右外连接 全外连接
我们之前用错误的代码得到的笛卡尔乘积 其实是个TEMP 暂时的 虚拟的 结果集
也就是 我们连接条件 筛选, 就是从笛卡尔乘积结果 再进行筛选的
而笛卡尔乘积结果是从From语句表中得到的
至于筛选条件WHERE 又可能是从连接条件的结果再筛选得来的
一环扣一环
那么,接下来下一节,我们来进行92标准的 内连接的学习,包含等值连接 非等值连接 自连接
数据库学习之MySQL (十四)—— 92标准的 非等值连接 自连接