多表查询的分类
内连接:用左边表的记录去匹配右边表的记录,如果符合条件就展示
隐式内连接:看不到JOIN关键字,条件使用WHERE 指定 SELECT 字段名 FROM 左表 右表 WHERE 条件;
格式
SELECT 展示字段 FROM 表 WHERE 条件;
显式内连接:使用 INNER JOIN … ON 语句, 可以省略 INNER SELECT 字段名 FROM 左表 INNER JOIN 右表 ON 条件;
格式
SELECT 展示字段 FROM 左表 INNER JOIN 右表 ON 条件;
内连接使用步骤
- 确定查询的表
- 确定表的连接条件
- 确定查询字段
左外连接:以左表为基准,右表没有显示为null
格式
select * from 左表 left outer join 右表 on 条件;
右外连接:以右表为基准,右表没有显示为null
格式
select * from 左表 right outer 右表 on 条件;
子查询
一条select 语句的结果作为另一条select 语法的一部分
- 子查询的结果又三种
- 子查询的结果是一个值;
- 子查询结果是单列多行;
- 子查询结果是多列多行;
- 子查询的结果是一个值;
子查询只要是单列肯定是在where后面作为条件,子查询只要是多列多行,肯定在from后面作为表
查询结果要是单列多行的话将结果作为条件,使用 in 关键字作为选择
案例
建表语句
-- 创建库
CREATE DATABASE IF NOT EXISTS test4 CHARACTER SET utf8
-- 创建部门表
CREATE TABLE IF NOT EXISTS dept(
id INT PRIMARY KEY, -- 部门 id
dname VARCHAR (20), -- 部门名字
loc VARCHAR(20) -- 部门位置
)
-- 添加数据
INSERT INTO dept VALUES(10,'教研部','北京'),
(20,'学工部','上海'),
(30,'销售部','广州'),
(40,'财务部','深圳');
-- 创建职务表
CREATE TABLE job (
id INT,
jname VARCHAR (20), -- 名称
descripition VARCHAR(50) -- 描述
)
-- 设置主键
ALTER TABLE job ADD CONSTRAINT j_fk PRIMARY KEY (id)
-- 添加职务
INSERT INTO job VALUES(1, '董事长', '管理整个公司,接单'),
(2, '经理', '管理部门员工'),
(3, '销售员', '向客人推销产品'),
(4, '文员', '使用办公软件')
-- 创建职工表
CREATE TABLE emp(
id INT PRIMARY KEY,
ename VARCHAR(50), -- 员工姓名
job_id INT, -- 职务id
mgr INT , -- 上级领导
joindate DATE, -- 入职日期
salary DECIMAL(7,2), -- 工资
bonus DECIMAL(7,2), -- 奖金
dept_id INT, -- 所在部门编号
CONSTRAINT emp_jobid_ref_job_id_fk FOREIGN KEY (job_id) REFERENCES job(id),
CONSTRAINT emp_deptid_ref_dept_id_fk FOREIGN KEY (dept_id) REFERENCES dept(id)
)
-- 添加员工
INSERT INTO emp(id,ename,job_id,mgr,joindate,salary,bonus,dept_id) VALUES
(1001,'孙悟空',4,1004,'2000‐12‐17','8000.00',NULL,20),
(1002,'卢俊义',3,1006,'2001‐02‐20','16000.00','3000.00',30),
(1003,'林冲',3,1006,'2001‐02‐22','12500.00','5000.00',30),
(1004,'唐僧',2,1009,'2001‐04‐02','29750.00',NULL,20),
(1005,'李逵',4,1006,'2001‐09‐28','12500.00','14000.00',30),
(1006,'宋江',2,1009,'2001‐05‐01','28500.00',NULL,30),
(1007,'刘备',2,1009,'2001‐09‐01','24500.00',NULL,10),
(1008,'猪八戒',4,1004,'2007‐04‐19','30000.00',NULL,20),
(1009,'罗贯中',1,NULL,'2001‐11‐17','50000.00',NULL,10),
(1010,'吴用',3,1006,'2001‐09‐08','15000.00','0.00',30),
(1011,'沙僧',4,1004,'2007‐05‐23','11000.00',NULL,20),
(1012,'李逵',4,1006,'2001‐12‐03','9500.00',NULL,30),
(1013,'小白龙',4,1004,'2001‐12‐03','30000.00',NULL,20),
(1014,'关羽',4,1007,'2002‐01‐23','13000.00',NULL,10);
-- 创建工资等级表
CREATE TABLE salarygrade(
grade INT PRIMARY KEY,
losalary INT,
hisalary INT4
)
-- 添加5个工资等级
INSERT INTO salarygrade(grade,losalary,hisalary) VALUES
(1,7000,12000),
(2,12010,14000),
(3,14010,20000),
(4,20010,30000),
(5,30010,99990);
- 查询所有员工信息。显示员工编号,员工姓名,工资,职务名称,职务描述
SELECT e.id 员工ID,e.ename 员工名称,e.salary 工资,j.jname 职务名称,j.descripition 职务描述
FROM emp e,job j
WHERE j.id = e.job_id
-----------------------------------------------------------
SELECT e.id 员工ID,e.ename 员工名称,e.salary 工资,j.jname 职务名称,j.descripition 职务描述
FROM emp e
INNER JOIN job j
ON j.id = e.job_id
- 查询所有员工信息。显示员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置
SELECT e.id 员工ID,e.ename 员工名称,e.salary 工资,j.jname 职务名称,j.descripition 职务描述,d.dname 部门名称,d.loc 部门位置FROM
emp e,job j,dept d WHERE
e.job_id = j.id AND e.dept_id = d.id;
------------------------------------------
SELECT e.id 员工ID,e.ename 员工名称,e.salary 工资,j.jname 职务名称,j.descripition 职务描述,d.dname 部门名称,d.loc 部门位置 FROM
emp e INNER JOIN dept d INNER JOIN job j ON
e.job_id = j.id AND e.dept_id = d.id;
- 查询所有员工信息。显示员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
SELECT e.ename 员工姓名,e.salary 工资,j.jname 职务名称,j.descripition 职务描述,d.dname 部门名称,d.loc 部门位置, s.grade 工资等级 FROM
emp e,dept d,job j,salarygrade s WHERE
e.job_id = j.id AND e.dept_id = d.id AND e.salary < hisalary AND e.salary > losalary
ORDER BY s.grade DESC
------------------------------------------
SELECT e.ename 员工姓名,e.salary 工资,j.jname 职务名称,j.descripition 职务描述,d.dname 部门名称,d.loc 部门位置, s.grade 工资等级 FROM
emp e INNER JOIN dept d INNER JOIN salarygrade s INNER JOIN job j
ON e.job_id = j.id AND e.dept_id = d.id AND e.salary BETWEEN s.losalary AND s.hisalary
ORDER BY s.grade DESC
- 查询经理的信息。显示员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
SELECT e.ename 姓名,e.salary 工资,j.jname 职务名称,j.descripition 职务描述,d.dname 部门名称,d.loc 部门位置,s.grade 工资等级 FROM
emp e INNER JOIN dept d INNER JOIN job j INNER JOIN salarygrade s ON
e.job_id = j.id AND e.dept_id = d.id AND e.salary BETWEEN s.losalary AND s.hisalary
ORDER BY d.dname;
---------------------------------------
SELECT e.ename 姓名,e.salary 工资,j.jname 职务名称,j.descripition 职务描述,d.dname 部门名称,d.loc 部门位置,s.grade 工资等级 FROM
emp e,dept d,job j,salarygrade s WHERE
e.job_id = j.id AND e.dept_id = d.id AND e.salary BETWEEN s.losalary AND s.hisalary
ORDER BY d.dname;
- 查询出部门编号、部门名称、部门位置、部门人数
SELECT d.id 部门编号, d.dname 部门名称,d.loc 部门位置,e. 部门人数
FROM dept d ,(SELECT COUNT(*) 部门人数,dept_id FROM emp GROUP BY dept_id) e
WHERE d.id = e.dept_id
----------------------------------------
SELECT d.id 部门编号,d.dname 部门名称,d.loc 部门位置,e. 部门人数
FROM dept d INNER JOIN (SELECT COUNT(*) 部门人数,dept_id FROM emp GROUP BY dept_id) e
ON d.id = e.dept_id
多表查询练习
#########################################################
#省份和市
#########################################################
#创建省份表
CREATE TABLE province(
pid INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10),
descripition VARCHAR(20)
);
#创建市表
CREATE TABLE city(
cid INT,
NAME VARCHAR(10),
descripition VARCHAR(20),
pid INT
);
#创建外键约束
ALTER TABLE city ADD CONSTRAINT FOREIGN KEY (pid) REFERENCES province (pid);
#########################################################
#用户和角色
#########################################################
#创建用户表
CREATE TABLE USER (
uid INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(10),
PASSWORD VARCHAR(20)
);
#创建角色表
CREATE TABLE role(
rid INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10)
);
#创建关联表
CREATE TABLE user_role(
urid INT,
uid INT,
rid INT
);
#创建外键约束
ALTER TABLE user_role ADD CONSTRAINT FOREIGN KEY (uid) REFERENCES USER (uid);
ALTER TABLE user_role ADD CONSTRAINT FOREIGN KEY (rid) REFERENCES role(rid);
#########################################################
#商品和分类
#########################################################
#分类表
CREATE TABLE category(
cid INT PRIMARY KEY AUTO_INCREMENT,
cname VARCHAR(30)
);
#商品表
CREATE TABLE products(
pid VARCHAR(10) PRIMARY KEY,
pname VARCHAR(30),
price INT,
flag VARCHAR(2), #是否上架标记为:1表示上架、0表示下架
category_id VARCHAR(32),
);
#添加外键约束
ALTER TABLE products ADD CONSTRAINT FOREIGN KEY (category_id) REFERENCES category (cid);
#分类数据
INSERT INTO category(cid,cname) VALUES('c001','家电');
INSERT INTO category(cid,cname) VALUES('c002','服饰');
INSERT INTO category(cid,cname) VALUES('c003','化妆品');
INSERT INTO category(cid,cname) VALUES('c004','奢侈品');
#商品数据
INSERT INTO products(pid, pname,price,flag,category_id) VALUES('p001','联想',5000,'1','c001');
INSERT INTO products(pid, pname,price,flag,category_id) VALUES('p002','海尔',3000,'1','c001');
INSERT INTO products(pid, pname,price,flag,category_id) VALUES('p003','雷神',5000,'1','c001');
INSERT INTO products(pid, pname,price,flag,category_id) VALUES('p004','JACK JONES',800,'1','c002');
INSERT INTO products(pid, pname,price,flag,category_id) VALUES('p005','真维斯',200,'1','c002');
INSERT INTO products(pid, pname,price,flag,category_id) VALUES('p006','花花公 子',440,'1','c002');
INSERT INTO products(pid, pname,price,flag,category_id) VALUES('p007','劲霸',2000,'1','c002');
INSERT INTO products(pid, pname,price,flag,category_id) VALUES('p008','香奈儿',800,'1','c003');
INSERT INTO products(pid, pname,price,flag,category_id) VALUES('p009','相宜本 草',200,'1','c003');
#交叉查询数据:产生笛卡尔积
SELECT * FROM products category;
#内连接查询
#隐试内连接查询:使用where判断,避免笛卡尔积产生
SELECT * FROM products p, category c WHERE p.category_id = c.cid AND p.flag='1';
#显式内连接 SELECT * FROM 左表 INNER[可以省略] JOIN 右表 ON 条件;
SELECT * FROM products p INNER JOIN category c ON p.category_id = c.cid AND p.flag='1';
#外链接查询:
#左外链接查询:以左表为基准,右表没有的数据显式null 格式:SELECT * FROM 左表 LEFT OUTER[可以省略] JOIN 右表 ON 条件
SELECT cname, COUNT(category_id) FROM products p LEFT OUTER JOIN category c ON p.category_id = c.cid GROUP BY cname;
#右外链接查询:以右表为基准,左表没有的数据显式null
SELECT cname,COUNT(category_id) FROM products p RIGHT OUTER JOIN category c ON p.category_id = c.cid GROUP BY cname;
#查询分类名称和分类下商品数量
SELECT c.cname, COUNT(category_id) FROM category c,products p WHERE c.cid = p.category_id GROUP BY c.cname; #这种情况查的是交集,
SELECT c.cname, COUNT(category_id) FROM category c LEFT OUTER JOIN products p ON c.cid = p.category_id GROUP BY cname; #这种情况查询的是并集,并且是以左侧为基准
SELECT c.cname, COUNT(category_id) FROM category c RIGHT OUTER JOIN products p ON c.cid = p.category_id GROUP BY cname; #这种情况查询的也是并集,知识以右表为基准,但是右表中没有c004的分类
#子查询:一条SELECT语句的结果作为另一条SELECT语句语法的一部分
#查询化妆品分类商家商品的详情
#隐试内连接查询方式
SELECT p.* FROM products p, category c WHERE p.category_id = c.cid AND p.category_id = 'c003';
#显式内连接查询方式
SELECT p.* FROM products p INNER JOIN category c ON p.category_id = c.cid AND p.category_id = 'c003';
#子查询
SELECT p.* FROM products p,category c WHERE p.category_id = (SELECT cid FROM category WHERE cname = '化妆品') AND p.category_id = c.cid;