准备数据:
use db1;
-- 创建用户表
CREATE TABLE user(
id INT PRIMARY KEY AUTO_INCREMENT, -- 用户id
NAME VARCHAR(20), -- 用户姓名
age INT -- 用户年龄
);
-- 添加数据
INSERT INTO user VALUES (NULL,'张三',23),(NULL,'李四',24),(NULL,'王五',25),(NULL,'赵六',26);
-- 订单表
CREATE TABLE orderList(
id INT PRIMARY KEY AUTO_INCREMENT, -- 订单id
number VARCHAR(30), -- 订单编号
uid INT, -- 外键字段
CONSTRAINT ou_fk FOREIGN KEY (uid) REFERENCES user(id)
);
-- 添加数据
INSERT INTO orderList VALUES (NULL,'test001',1),(NULL,'test002',1),(NULL,'test003',2),
(NULL,'test004',2),(NULL,'test005',3),(NULL,'test006',3),(NULL,'test007',NULL);
-- 商品分类表
CREATE TABLE category(
id INT PRIMARY KEY AUTO_INCREMENT, -- 商品分类id
NAME VARCHAR(10) -- 商品分类名称
);
-- 添加数据
INSERT INTO category VALUES (NULL,'手机数码'),(NULL,'电脑办公'),(NULL,'烟酒茶糖'),(NULL,'鞋靴箱包');
-- 商品表
CREATE TABLE product(
id INT PRIMARY KEY AUTO_INCREMENT, -- 商品id
NAME VARCHAR(30), -- 商品名称
cid INT, -- 外键字段
CONSTRAINT cp_fk FOREIGN KEY (cid) REFERENCES category(id)
);
-- 添加数据
INSERT INTO product VALUES (NULL,'华为手机',1),(NULL,'小米手机',1),(NULL,'联想电脑',2),
(NULL,'苹果电脑',2),(NULL,'中华香烟',3),(NULL,'玉溪香烟',3),(NULL,'计生用品',NULL);
-- 中间表
CREATE TABLE us_pro(
upid INT PRIMARY KEY AUTO_INCREMENT, -- 中间表id
uid 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),(NULL,1,2),(NULL,1,3),(NULL,1,4),
(NULL,1,5),(NULL,1,6),(NULL,1,7),(NULL,2,1),(NULL,2,2),(NULL,2,3),(NULL,2,4),
(NULL,2,5),(NULL,2,6),(NULL,2,7),(NULL,3,1),(NULL,3,2),(NULL,3,3),(NULL,3,4),
(NULL,3,5),(NULL,3,6),(NULL,3,7),(NULL,4,1),(NULL,4,2),(NULL,4,3),(NULL,4,4),
(NULL,4,5),(NULL,4,6), (NULL,4,7);
笛卡尔积:指A表和B表所有组合的情况,在查询数据时需消除笛卡尔积现象
-- 多表查询,笛卡尔积现象
select * from product , category;
-- 消除笛卡尔积现象
select * from product p, category c where p.cid = c.id;
内连接查询的是两张表有交集的数据(有主外键关联的数据)
-- 标准语法 INNER可写可不写
SELECT 列名 FROM 表1 [INNER] JOIN 表2 ON 表1.公共字段 = 表2.公共字段;
-- 查询用户信息和对应的订单信息,起别名
SELECT u.name ,o.number FROM user u JOIN orderList o ON u.id = o.uid;
-- 查询用户姓名,年龄。和订单编号,标准查询格式
SELECT u.name,u.age,o.number FROM USER u INNER JOIN orderList o ON u.id = o.uid;
-- 标准语法
SELECT 列名 FROM 表1,表2 WHERE 条件 表1.公共字段 = 表2.公共字段;
-- 隐式内连接查询
-- 查询用户姓名和订单编号
SELECT u.name,o.number FROM USER u, orderList o WHERE u.id=o.uid;
问题:下面这两个语句执行结果是否一致
SELECT u.name ,o.number FROM user u JOIN orderList o ON u.id = o.uid;
SELECT u.name ,o.number FROM orderList o JOIN user u ON u.id = o.uid;
答:一致,因为内连接获取的是两个表的公共部分
查询左表的全部数据,和左右两张表有交集部分的数据。
演示:
-- 标准语法 OUTER可写可不写
SELECT 列名 FROM 表1 LEFT [OUTER] JOIN 表2 ON 表1.公共字段 = 表2.公共字段;
-- 查询所有用户信息,以及用户对应的订单信息
SELECT u.*,o.number FROM USER u LEFT OUTER JOIN orderList o ON u.id = o.uid;
查询右表的全部数据,和左右两张表有交集部分的数据
-- 基本语法 OUTER可写可不写
SELECT 列名 FROM 表1 RIGHT [OUTER] JOIN 表2 ON 表1.公共字段 = 表2.公共字段;
select 列名 from 表1 right join 表2 on 表1.公共字段=表2.公共字段
-- 查询所有订单信息,以及订单所属的用户信息
SELECT u.*,o.* FROM USER u RIGHT OUTER JOIN orderList o ON u.id=o.uid;
右连接也可以变成左连接,所以开发使用左连接比较多
SELECT u.*, o.* FROM orderList o LEFT JOIN USER u ON u.id=o.uid;
子连接查询,可以是内连接也可以是外连接查询,也就是自己连接自己。
-- 自连接语法:
select 字段列表 from 表1 别名1 JOIN 表1 别名2 ON 别名1.公共字段 = 别名2.公共字段;
-- 创建员工表
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);
-- 查询所有员工的姓名及其直接上级的姓名,
SELECT e1.name, e2.name FROM employee e1,employee e2 WHERE e1.mgr = e2.id;
-- 查询所有员工的姓名及其所属上级的姓名,没有上级的员工也需要查询
/*
分析:
员工姓名 employee表 直接上级姓名 employee表
条件:employee.mgr = employee.id
查询左表的全部数据,和左右两张表交集部分数据,使用左外连接
*/
SELECT e1.name, e1.mgr, e2.id, e2.name FROM employee e1 LEFT JOIN employee e2 ON e1.mgr = e2.id;
就是把多次查询的结果合并起来,形成一个新的查询结果集。
对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致,UNION ALL
会将全部的数据直接合并在一起,UNION
会把合并后的数据去重
-- 语法
-- SELECT 字段列表 FROM 表A UNION [ALL] SELECT 字段列表 FROM 表B;
-- 查询薪资大于5000,年龄大于50的员工
select * from user where age > 20;
select * from user where salary > 5000;
-- 把这两个语句连接起来就是联合查询
select * from user where age > 20 union all select * from user where salary > 5000;
-- 去重
select * from user where age > 20 union select * from user where salary > 5000;
- SQL语句中嵌套了SELECT语句,称为嵌套查询或子查询。
子查询外部的语句可以是INSERT/UPDATE/DELETE/SELECT的任意一个
根据查询结果不同,子查询分为:
子查询返回的结果是单个值(数字、字符串、日期等),这种查询称为标量子查询。
常用的操作符:=、<>、>、 >=、<、<=
演示:
-- 查询手机数码分类下的所有商品信息,先查询到分类id,再用分类id查询所有商品
select id from category where name = '手机数码';
select * from product where cid = 1;
-- 使用标量子查询实现
select * from product where cid = (select id from category where name = '手机数码');
子查询的返回结果是一列(可以是多行),这种子查询称为列子查询
常用的操作符:IN、NOT IN、ANY、SOME、ALL
操作符 | 含义 |
---|---|
IN | 在指定的集合范围之内,多选一 |
NOT IN | 不在指定的集合范围之内 |
ANY | 子查询返回列表中,有任意一个满足即可 |
SOME | 子ANY等同,使用SOME的地方都可以使用ANY |
ALL | 子查询返回列表的所有值都必须满足 |
演示:
-- 查询"手机数码"分类下的所有商品价格,先查id
select id from category where name = '手机数码';
-- 再查分类下所有的商品价格
select price from product where cid = (select id from category where name = '手机数码');
-- 查询比"手机数码"全部商品价都要高的商品信息(总和)
select * from product where price > all (select price from product where cid = (select id from category where name = '手机数码'));
-- 查询比"手机数码"分类下任意一个价格高的商品信息,使用any和some一样
select * from product where price > any (select price from product where cid = (select id from category where name = '手机数码'));
子查询的返回结果是一行(可以是多列),这种子查询称为行子查询。
常用的操作符:=、<>、IN、NOT IN
-- 查询"华为手机"的价格及所属分类下相同价格的商品信息,先查华为手机的所属分类
select cid from product where name ='华为手机';
-- 查询该分类下与华为手机价格相同的商品信息,对比查询结果即可
select * from product where (cid) = (1);
-- 转换成动态的查询结果
select * from product where (cid) = (select cid from product where name ='华为手机');
子查询的返回结果是多行多列,这种子查询称为表子查询
常用的操作符:IN
-- 查询和'华为手机'、'小米手机'的分类、价格相同的商品信息
-- 先查'华为手机'、'小米手机'的分类、价格
select name,price from product where name = '华为手机' or name = '小米手机';
select * from product where (name,price) in(select name,price from product where name = '华为手机' or name = '小米手机');
-- 查询商品上架时间是'2023-01-01'之后的商品信息及所属分类信息,把结果作为一个表
select * from product where putawayDate > '2023-01-01';
-- 查询这些商品及分类信息
select p.*,c.* from ( select * from product where putawayDate > '2023-01-01') p left join category c on c.id = p.cid;
1、查询用户的id、姓名、年龄、订单编号
/*
分析:
user用户表:id、姓名、年龄
orderList订单表:订单编号
条件:user.id = orderList.uid
*/
SELECT
u.id,
u.NAME,
u.age,
o.number
FROM
USER u,
orderList o
WHERE
u.id = o.uid;
2、查询所有的用、用户的id、姓名、年龄、订单编号
/*
分析:
user表:id、姓名、年龄
orderList表:订单编号
条件:user.id = orderList.uid
查询所有用户,使用左外连接
*/
SELECT
u.id,
u.NAME,
u.age,
o.number
FROM
USER u
LEFT INNER JOIN orderList o ON u.id = o.uid;
3、查询所有的订单、用户的id、姓名、年龄、订单编号
/*
分析:
user表:id、姓名、年龄
orderList表:订单编号
条件:user.id = orderList.uid
查询所有订单,使用右外连接
*/
SELECT
u.id,
u.NAME,
u.age,
o.number
FROM
USER u
RIGHT OUTER JOIN orderList o ON u.id = o.uid;
4、查询用户年龄大于23岁的信息、显示用户的id、姓名、年龄、订单编号
/*
分析:
user表:id、姓名、年龄
orderList表:订单编号
条件:user.id = orderList.uid AND user.age > 23;
*/
SELECT
u.id,
u.NAME,
u.age,
o.number
FROM
USER u,
orderList o
WHERE
u.id = o.uid
AND u.age > 23;
5、查询张三、李四用户的信息。显示用户的id、姓名、年龄。订单编号
/*
分析:
user表:id、姓名、年龄
orderList表:订单编号
条件:user.id = orderList.uid AND user.name IN ('张三','李四');
*/
SELECT
u.id,
u.NAME,
u.age,
o.number
FROM
USER u,
orderList o
WHERE
u.id = o.uid
AND u.NAME IN ( '张三', '李' );
6、查询商品分类的id、分类名称、分类下的商品名称
/*
分析:
category表:商品分类的编号、分类名称
product表:分类下的商品名称
条件:category.id = product.cid
*/
SELECT
c.id,
c.NAME,
p.cid
FROM
category c,
product p
WHERE
c.id = p.cid;
7、查询所有的商品分类、商品分类的id、分类名称、分类下的商品名称
/*
分析:
category表:商品分类的编号、分类名称
product:表分类下的商品名称
条件:category.id = product.cid
查询所有的商品分类,使用左外连接
*/
SELECT
c.id,
c.NAME,
p.NAME
FROM
category c
LEFT OUTER JOIN product p ON c.id = p.cid;
8、查询所有的商品信息、商品分类的id、分类名称、分类下的商品名称
/*
分析:
category表:商品分类的编号、分类名称
product表:分类下的商品名称
条件:category.id = product.cid
查询所有的商品信息,使用右外连接
*/
SELECT
c.id,
c.NAME,
p.NAME
FROM
category c
RIGHT OUTER JOIN product p
ON c.id = p.cid;
9、查询所有的用户和该用户能查看的所有的商品、显示用户的id、姓名、年龄、商品名称
/*
分析:
user表:用户的id、姓名、年龄
us_pro中间表:
product表:商品名称
条件:us_pro.uid = user.id AND us_pro.pid = product.id
*/
SELECT
u.id,
u.NAME,
u.age,
p.NAME
FROM
USER u,
product p,
us_pro up
WHERE
up.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 ('张三','李四')
*/
SELECT
u.id,
u.NAME,
u.age,
p.NAME
FROM
USER u,
product p,
us_pro up
WHERE
up.uid = u.id
AND up.pid = p.id
AND u.NAME
IN ( '张三', '李四' );