mysql基础(六)子查询与多表连接查询

建表:

CREATE TABLE no6(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(10),
	age TINYINT,
	money INT,
	tel CHAR(11)
);

插入数据:

INSERT INTO no6 VALUES(NULL,'张三',30,2000,13565234121),(NULL,'李四',23,1000,13814526352),(NULL,'王五',40,8000,13913656352),(NULL,'赵六',33,8000,13913121234)

使用子查询为条件进行查询:

SELECT NAME FROM no6 WHERE age IN (SELECT age FROM no6 WHERE money >=2000) AND tel LIKE '%34'

随便写的哈,虽然这种子查询没有意义

在这里插入图片描述
更新、删除操作也可以使用子查询,但是子查询不能,更删操作表和子查询表不能相同:
操作与子查询是同一张表:
更新语句

UPDATE no6 SET money=(SELECT MAX(money) FROM no6)/2 WHERE id=(SELECT id FROM no6 ORDER BY money LIMIT 1)

报错:

在这里插入图片描述
删除语句

DELETE FROM no6 WHERE id=(SELECT id FROM no6 ORDER BY money LIMIT 1)

也是报错
在这里插入图片描述

更删no6表,子查询使用no5表
更新

UPDATE no6 SET money=(SELECT MAX(money) FROM no5)/2 WHERE id=(SELECT id FROM no5 ORDER BY money LIMIT 1)

在这里插入图片描述
删除

DELETE FROM no6 WHERE id=(SELECT id FROM no5 ORDER BY money LIMIT 1)

在这里插入图片描述
any、all、exists用法:
先插入几条数据

INSERT INTO no6 VALUES(NULL,'二蛋',35,1500,13565234121),(NULL,'大柱',28,3400,13814526352),(NULL,'铁头',42,9100,13913656352),(NULL,'小吴',37,4500,13913121234)

在这里插入图片描述
测试语句

SELECT money FROM no6 WHERE money>2000 AND money<6000

查询结果
在这里插入图片描述
就以这条语句为子查询(结果是3400-4500)为取值范围:

SELECT * FROM no6 WHERE money >ANY(SELECT money FROM no6 WHERE money>2000 AND money<6000)

在这里插入图片描述
结果中有4500,没有3000。any是任意的意思,>any()的取值范围是大于括号里面的任意一个数,返回结果就是大于最小的数。
改成<any

SELECT * FROM no6 WHERE money <ANY(SELECT money FROM no6 WHERE money>2000 AND money<6000)

在这里插入图片描述
结果里面有3400,<any返回就是小于取值范围中的最大值。

再改成=any(any与some完全相同)

SELECT * FROM no6 WHERE money =ANY(SELECT money FROM no6 WHERE money>2000 AND money<6000)

在这里插入图片描述

=any也就是返回取值范围内的任意值,=any相当于in,只是in的取值范围里可以直接放数字

把any改成all

SELECT * FROM no6 WHERE money =ALL (SELECT money FROM no6 WHERE money>2000 AND money<6000)

在这里插入图片描述
结果为空,=all只有在取值范围只有一条的情况下才生效。

改成>all

SELECT * FROM no6 WHERE money >ALL (SELECT money FROM no6 WHERE money>2000 AND money<6000)

在这里插入图片描述
结果大于取值范围内的所有值。
改成<all

SELECT * FROM no6 WHERE money <ALL (SELECT money FROM no6 WHERE money>2000 AND money<6000)

在这里插入图片描述
结果小于取值范围内的所有值

改成<>all

SELECT * FROM no6 WHERE money <>ALL (SELECT money FROM no6 WHERE money>2000 AND money<6000)

在这里插入图片描述
not in相当于<>all,但是not in的取值范围可以直接以数字表示

SELECT * FROM no6 WHERE money NOT IN(3400,4500)

在这里插入图片描述
exists(),查看是否存在:

SELECT * FROM no6 WHERE EXISTS(SELECT * FROM no6 WHERE NAME='王八')

在这里插入图片描述
因为子查询结果不存在,查询不生效

SELECT * FROM no6 WHERE EXISTS(SELECT * FROM no6 WHERE NAME='大柱')

在这里插入图片描述
当子查询结果存在,查询生效。

多表连接:
先建表并插入数据

CREATE TABLE no7(
	id INT PRIMARY KEY AUTO_INCREMENT,
	sex CHAR(5) DEFAULT'男',
	NAME VARCHAR(10),
	address VARCHAR(20)
);
INSERT INTO no7 VALUES(NULL,'女','张三','八一路'),(NULL,'男','赵六','人民路'),(NULL,'男','小强','解放路'),(NULL,'女',NULL,'黄泉路');

多表连接

在这里插入图片描述

内连接示例:

SELECT * FROM no6 t1 JOIN no7 t2 ON t1.id=t2.id

在这里插入图片描述
返回结果是两表的交集。join前的inner可以省略,t1和t2是两张表的别名,用如下语句同样可以实现如上功能:

SELECT * FROM no6,no7 WHERE no6.id=no7.id

这是sql92语法,也就是连接条件和过滤条件都在一起(where后)。
在这里插入图片描述
指定字段进行查询的时候要注意两表是否有同名字段,如同名要说明是哪张表的:

SELECT t1.name,age,sex,t2.name FROM no6 t1 JOIN no7 t2 ON t1.id=t2.id

在这里插入图片描述
外连接分为左连接和右连接
外连接中的表分主次,不像内连接两表平等。
左连接示例:

SELECT * FROM no6 a LEFT OUTER JOIN no7 b ON a.id=b.id

在这里插入图片描述
左外连接返回结果是右表的一部分(交集)和左表的全部,join前的outer可以省略。
当如上查询语句加上右表关联字段为空的条件:

SELECT * FROM no6 a LEFT OUTER JOIN no7 b ON a.id=b.id WHERE b.id IS NULL

在这里插入图片描述
返回结果是左表减去交集后的剩余部分,也就是左表与右表的差集。
右外连接演示:

SELECT * FROM no6 a RIGHT JOIN no7 b ON a.id=b.id

在这里插入图片描述
返回结果为左表一部分(交集),右表全部。
语句后面加上条件左表关联字段为空:

SELECT * FROM no6 a RIGHT JOIN no7 b ON a.id=b.id WHERE a.id IS NULL

在这里插入图片描述
返回结果只有右表减去交集后剩余部分(右表与左表的差集)。
全连接:
mysql中是没有全连接的,但是我们可以用union实现,union用来实现多条select的语句的联合,可以把多条SELECT语句的结果组合到一个结果集合中。
先做个演示:

SELECT NAME FROM no6 WHERE id>1
UNION
SELECT NAME FROM no7 WHERE id>1;

union是默认去重的,union all不去重。union进行表连接可以变笛卡尔乘积为表之总和,也就是变乘法为加法
这两条语句没有union的时候是不能同时执行的,而现在的结果是怎么呢?
在这里插入图片描述
值得注意的是使用union的时候每条语句的查询字段数量要相同(在Oracle中要求类型也相同)。
全连接演示:

SELECT * FROM no6 a LEFT JOIN no7 b ON a.id=b.id 
UNION
SELECT * FROM no6 a RIGHT JOIN no7 b ON a.id=b.id 

语句也很简单,就是左连接和右连接用union联合,结果如下:
在这里插入图片描述
返回的是两张表的所有内容,也就是两表并集。
再用两张表的关联字段为空过滤掉两表交集:

SELECT * FROM no6 a LEFT JOIN no7 b ON a.id=b.id  WHERE b.id IS NULL     
UNION
SELECT * FROM no6 a RIGHT JOIN no7 b ON a.id=b.id  WHERE a.id IS NULL   

这两条查询语句之前都已经测试过了,左连接过滤掉交集返回结果是左表与右表差集,右连接过滤掉交集返回结果是右表与左表的差集。那么联合语句返回结果就是除了两表除了交集之外的所有内容,也就是两表的对称差集:
在这里插入图片描述
自连接:
自连接是一种特殊的连接,把一张表当成两张表使用,也就是自己连自己。
重建no7表,并插入数据:

CREATE TABLE no7(
	id INT PRIMARY KEY AUTO_INCREMENT,
	sex CHAR(5) DEFAULT'男',
	NAME VARCHAR(10),
	address VARCHAR(20),
	cid INT 
);
INSERT INTO no7 VALUES(NULL,'女','张三','八一路',4),(NULL,'男','赵六','人民路',3),(NULL,'男','小强','解放路',2),(NULL,'女',NULL,'黄泉路',1);

在这里插入图片描述
进行自连接查询:

SELECT a.id,a.name AS '正序名字',b.name AS '倒序名字' FROM no7 a INNER JOIN no7 b ON a.id=b.cid  ORDER BY a.id      

在这里插入图片描述
以表自身两个字段进行关联,然后以对同一个字段name进行了两次查询。
有一张图对各种表连接进行了说明,不是mysql的,所以仅供参考:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值