多表查询分类:
- 内连接查询
- 显式内连接
- 隐式内连接
- 外连接查询
- 左外连接
- 右外连接
- 子查询
- 自关联查询
准备数据:
-- 创建user表
CREATE TABLE USER(id INT PRIMARY KEY AUTO_INCREMENT, -- 用户idNAME VARCHAR(20), -- 用户姓名age INT -- 用户年龄
);
-- 添加数据
INSERT INTO USER VALUES (NULL,'张三',23);
INSERT INTO USER VALUES (NULL,'李四',24);
INSERT INTO USER VALUES (NULL,'王五',25);
INSERT INTO USER VALUES (NULL,'赵六',26);-- 订单表
CREATE TABLE orderlist(id INT PRIMARY KEY AUTO_INCREMENT, -- 订单idnumber VARCHAR(30), -- 订单编号uid INT, -- 外键字段CONSTRAINT ou_fk FOREIGN KEY (uid) REFERENCES USER(id)
);
-- 添加数据
INSERT INTO orderlist VALUES (NULL,'test001',1);
INSERT INTO orderlist VALUES (NULL,'test002',1);
INSERT INTO orderlist VALUES (NULL,'test003',2);
INSERT INTO orderlist VALUES (NULL,'test004',2);
INSERT INTO orderlist VALUES (NULL,'test005',3);
INSERT INTO orderlist VALUES (NULL,'test006',3);
INSERT INTO orderlist VALUES (NULL,'test007',NULL);-- 商品分类表
CREATE TABLE category(id INT PRIMARY KEY AUTO_INCREMENT, -- 商品分类idNAME VARCHAR(10) -- 商品分类名称
);
-- 添加数据
INSERT INTO category VALUES (NULL,'手机数码');
INSERT INTO category VALUES (NULL,'电脑办公');
INSERT INTO category VALUES (NULL,'烟酒茶糖');
INSERT INTO category VALUES (NULL,'鞋靴箱包');-- 商品表
CREATE TABLE product(id INT PRIMARY KEY AUTO_INCREMENT, -- 商品idNAME VARCHAR(30), -- 商品名称cid INT, -- 外键字段CONSTRAINT cp_fk FOREIGN KEY (cid) REFERENCES category(id)
);
-- 添加数据
INSERT INTO product VALUES (NULL,'华为手机',1);
INSERT INTO product VALUES (NULL,'小米手机',1);
INSERT INTO product VALUES (NULL,'联想电脑',2);
INSERT INTO product VALUES (NULL,'苹果电脑',2);
INSERT INTO product VALUES (NULL,'中华香烟',3);
INSERT INTO product VALUES (NULL,'玉溪香烟',3);
INSERT INTO product VALUES (NULL,'计生用品',NULL);-- 中间表
CREATE TABLE us_pro(upid INT PRIMARY KEY AUTO_INCREMENT, -- 中间表iduid INT, -- 外键字段。需要和用户表的主键产生关联pid INT, -- 外键字段。需要和商品表的主键产生关联CONSTRAINT up_fk1 FOREIGN KEY (uid) REFERENCES USER(id),CONSTRAINT up_fk2 FOREIGN KEY (pid) REFERENCES product(id)
);
-- 添加数据
INSERT INTO us_pro VALUES (NULL,1,1);
INSERT INTO us_pro VALUES (NULL,1,2);
INSERT INTO us_pro VALUES (NULL,1,3);
INSERT INTO us_pro VALUES (NULL,1,4);
INSERT INTO us_pro VALUES (NULL,1,5);
INSERT INTO us_pro VALUES (NULL,1,6);
INSERT INTO us_pro VALUES (NULL,1,7);
INSERT INTO us_pro VALUES (NULL,2,1);
INSERT INTO us_pro VALUES (NULL,2,2);
INSERT INTO us_pro VALUES (NULL,2,3);
INSERT INTO us_pro VALUES (NULL,2,4);
INSERT INTO us_pro VALUES (NULL,2,5);
INSERT INTO us_pro VALUES (NULL,2,6);
INSERT INTO us_pro VALUES (NULL,2,7);
INSERT INTO us_pro VALUES (NULL,3,1);
INSERT INTO us_pro VALUES (NULL,3,2);
INSERT INTO us_pro VALUES (NULL,3,3);
INSERT INTO us_pro VALUES (NULL,3,4);
INSERT INTO us_pro VALUES (NULL,3,5);
INSERT INTO us_pro VALUES (NULL,3,6);
INSERT INTO us_pro VALUES (NULL,3,7);
INSERT INTO us_pro VALUES (NULL,4,1);
INSERT INTO us_pro VALUES (NULL,4,2);
INSERT INTO us_pro VALUES (NULL,4,3);
INSERT INTO us_pro VALUES (NULL,4,4);
INSERT INTO us_pro VALUES (NULL,4,5);
INSERT INTO us_pro VALUES (NULL,4,6);
INSERT INTO us_pro VALUES (NULL,4,7);
内连接:
查询原理:内连接查询的是两张表有交集的部分数据(有主外键关联的数据)
显式内连接
-- 内连接显示查询
-- 标准语法 INNER可写可不写
SELECT 列名 FROM 表名1 [INNER] JOIN 表名2 ON 条件;-- 查询用户信息和对应的订单信息
SELECT * FROM USER INNER JOIN orderlist ON USER.id = orderlist.uid;
SELECT * FROM USER JOIN orderlist ON USER.id = orderlist.uid;-- 查询用户信息和对应的订单信息,起别名
SELECT * FROM USER u JOIN orderlist o ON u.id = o.uid;-- 查询用户姓名,年龄。和订单编号,标准查询格式
SELECTu.`name`,-- 姓名u.`age`,-- 年龄o.`number` -- 订单编号FROMUSER u -- 用户表INNER JOIN orderlist o -- 订单表ON u.`id` = o.`uid`;
隐式内连接:
-- 隐式内连接
-- 标准语法
SELECT 列名 FROM 表名1,表名2 WHERE 条件;-- 查询用户姓名,年龄。和订单编号
SELECTu.`name`, -- 姓名u.`age`, -- 年龄o.`number` -- 订单编号
FROMUSER u, -- 用户表orderlist o -- 订单表
WHEREu.`id`=o.`uid`;
左外连接:
查询原理
查询左表的全部数据,和左右两张表有交集部分的数据
演示:
-- 标准语法 OUTER可写可不写
SELECT 列名 FROM 表名1 LEFT [OUTER] JOIN 表名2 ON 条件;-- 查询所有用户信息,以及用户对应的订单信息
SELECTu.`name`,-- 姓名u.`age`,-- 年龄o.`number` -- 订单编号FROMUSER u -- 用户表LEFT OUTER JOIN orderlist o -- 订单表ON u.`id` = o.`uid`;
右外连接:
查询原理
查询右表的全部数据,和左右两张表有交集部分的数据
-- 基本语法 OUTER可写可不写
SELECT 列名 FROM 表名1 RIGHT [OUTER] JOIN 表名2 ON 条件;
-- 查询所有订单信息,以及订单所属的用户信息
SELECTu.`name`, -- 姓名u.`age`, -- 年龄o.`number` -- 订单编号
FROMUSER u -- 用户表
RIGHT OUTER JOINorderlist o -- 订单表
ONu.`id`=o.`uid`;
子查询:
- 查询语句中嵌套了查询语句,将嵌套的查询称为子查询!
子查询的结果是单行单列的
- 可以将查询的结果作为另一条语句的查询条件,使用运算符进行判断!
-- 标准语法
SELECT 列名 FROM 表名 WHERE 列名=(SELECT 聚合函数(列名) FROM 表名 [WHERE 条件]);-- 查询年龄最高的用户姓名
SELECT MAX(age) FROM USER; -- 查询出最高年龄
SELECT NAME,age FROM USER WHERE age=26; -- 根据查询出来的最高年龄,查询姓名和年龄
SELECT NAME,age FROM USER WHERE age = (SELECT MAX(age) FROM USER); -- 这里就是把前面两条合体了
子查询-结果是多行单列的
可以作为条件,使用运算符in或not in进行判断!
-- 标准语法
SELECT 列名 FROM 表名 WHERE 列名 [NOT] IN (SELECT 列名 FROM 表名 [WHERE 条件]); -- 查询张三和李四的订单信息
SELECT id FROM USER WHERE NAME='张三' OR NAME='李四'; -- 查询张三和李四用户的id
SELECT number,uid FROM orderlist WHERE uid=1 OR uid=2; -- 根据id查询订单
SELECT * FROM orderlist WHERE uid IN (SELECT id FROM USER WHERE NAME='张三' OR NAME='李四');
子查询-结果是多行多列的
可以作为一张虚拟表参与查询!
-- 标准语法
SELECT 列名 FROM 表名 [别名],(SELECT 列名 FROM 表名 [WHERE 条件]) [别名] [WHERE 条件];-- 查询订单表中id大于4的订单信息和所属用户信息
SELECT * FROM orderlist WHERE id > 4;SELECTu.name,o.number
FROMUSER u,(SELECT * FROM orderlist WHERE id > 4) o
WHEREo.uid = u.id;
自关联查询:
同一张表中有数据关联。可以多次查询这同一个表!
比如:在employee表中,猪八戒的上级是唐僧,那么猪八戒就是有自关联的,就是同一张表数据之间有一定的数据关联
-- 创建员工表
CREATE TABLE employee(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(20),mgr INT,salary DOUBLE
);
-- 添加数据
INSERT INTO employee VALUES (1001,'孙悟空',1005,9000.00),
(1002,'猪八戒',1005,8000.00),
(1003,'沙和尚',1005,8500.00),
(1004,'小白龙',1005,7900.00),
(1005,'唐僧',NULL,15000.00),
(1006,'武松',1009,7600.00),
(1007,'李逵',1009,7400.00),
(1008,'林冲',1009,8100.00),
(1009,'宋江',NULL,16000.00);-- 查询所有员工的姓名及其直接上级的姓名,没有上级的员工也需要查询
/*
分析:员工姓名 employee表 直接上级姓名 employee表条件:employee.mgr = employee.id查询左表的全部数据,和左右两张表交集部分数据,使用左外连接
*/
SELECTt1.name, -- 员工姓名t1.mgr, -- 上级编号t2.id, -- 员工编号t2.name -- 员工姓名
FROMemployee t1 -- 员工表
LEFT OUTER JOINemployee t2 -- 员工表
ONt1.mgr = t2.id;
多表查询练习:
1、查询用户的id、姓名、年龄、订单编号
/*
分析:user用户表:id、姓名、年龄 orderlist订单表:订单编号条件:user.id = orderlist.uid
*/SELECTu.id,u.`NAME`,u.age,o.number
FROM`USER` u,orderlist o
WHEREu.id = o.uid;
2、查询所有的用、用户的id、姓名、年龄、订单编号
/*
分析:user表:id、姓名、年龄 orderlist表:订单编号条件:user.id = orderlist.uid查询所有用户,使用左外连接
*/SELECTu.id,u.`NAME`,u.age,o.number
FROM`USER` uLEFT INNER JOIN orderlist o ON u.id = o.uid;
3、查询所有的订单、用户的id、姓名、年龄、订单编号
/*
分析:user表:id、姓名、年龄 orderlist表:订单编号条件:user.id = orderlist.uid查询所有订单,使用右外连接
*/ SELECTu.id,u.`NAME`,u.age,o.number
FROM`USER` uRIGHT OUTER JOIN orderlist o ON u.id = o.uid;
4、查询用户年龄大于23岁的信息、显示用户的id、姓名、年龄、订单编号
/*
分析:user表:id、姓名、年龄 orderlist表:订单编号条件:user.id = orderlist.uid AND user.age > 23;
*/SELECTu.id,u.`NAME`,u.age,o.number
FROM`USER` u,orderlist o
WHEREu.id = o.uid AND u.age > 23;
5、查询张三、李四用户的信息。显示用户的id、姓名、年龄。订单编号
/*
分析:user表:id、姓名、年龄 orderlist表:订单编号条件:user.id = orderlist.uid AND user.name IN ('张三','李四');
*/SELECTu.id,u.`NAME`,u.age,o.number
FROM`USER` u,orderlist o
WHEREu.id = o.uid AND u.`NAME` IN ( '张三', '李' );
6、查询商品分类的id、分类名称、分类下的商品名称
/*
分析:category表:商品分类的编号、分类名称product表:分类下的商品名称 条件:category.id = product.cid
*/SELECTc.id,c.`NAME`,p.cid
FROMcategory c,product p
WHEREc.id = p.cid;
7、查询所有的商品分类、商品分类的id、分类名称、分类下的商品名称
/*
分析:category表:商品分类的编号、分类名称 product:表分类下的商品名称 条件:category.id = product.cid查询所有的商品分类,使用左外连接
*/
SELECTc.id,c.NAME,p.NAME
FROMcategory cLEFT OUTER JOIN product p ON c.id = p.cid;
8、查询所有的商品信息、商品分类的id、分类名称、分类下的商品名称
/*
分析:category表:商品分类的编号、分类名称product表:分类下的商品名称条件:category.id = product.cid查询所有的商品信息,使用右外连接
*/
SELECTc.id,c.NAME,p.NAME
FROMcategory cRIGHT OUTER JOIN product pON c.id = p.cid;
9、查询所有的用户和该用户能查看的所有的商品、显示用户的id、姓名、年龄、商品名称
/*
分析:user表:用户的id、姓名、年龄us_pro中间表:product表:商品名称条件:us_pro.uid = user.id AND us_pro.pid = product.id
*/
SELECTu.id,u.NAME,u.age,p.NAME
FROM`USER` u,product p,us_pro up
WHEREup.uid = u.id AND up.pid = p.id;
10、查询张三和李四这两个用户可以看到的商品。显示用户的id、姓名、年龄、商品名称
/*
分析:user表:用户的id、姓名、年龄product表:商品名称us_pro中间表:条件:us_pro.uid = user.id AND us_pro.pid = product.id AND user.name IN ('张三','李四')
*/
SELECTu.id,u.NAME,u.age,p.NAME
FROM`USER` u,product p,us_pro up
WHEREup.uid = u.id AND up.pid = p.id AND u.`NAME`IN ( '张三', '李四' );