赞
踩
在关系型数据库中,多表查询是一个至关重要的概念,它允许我们从多个表中提取相关数据。今天将详细介绍多表查询的基本概念、不同的多表关系类型、常用的SQL关键字以及如何通过SQL语句实现这些查询。
多表关系主要分为以下几种类型:
在多对多关系中,我们需要建立第三张表来存储两个表之间的关联。以下是关于学生、课程及其关系的示例。
- CREATE TABLE student (
- id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
- name VARCHAR(10) COMMENT '姓名',
- no VARCHAR(10) COMMENT '学号'
- ) COMMENT = '学生表';
-
- INSERT INTO student (id, name, no) VALUES
- (NULL, '熊绮丝', '2000100101'),
- (NULL, '谢进', '2000100102'),
- (NULL, '殷天正', '2000100103'),
- (NULL, '夷一笑', '2000100104');
- CREATE TABLE course (
- id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
- name VARCHAR(10) COMMENT '课程名称'
- ) COMMENT = '课程表';
-
- INSERT INTO course (id, name) VALUES
- (NULL, 'Java'),
- (NULL, 'PHP'),
- (NULL, 'MySQL'),
- (NULL, 'Hadoop');
- CREATE TABLE student_course (
- id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
- student_id INT NOT NULL COMMENT '学生ID',
- course_id INT NOT NULL COMMENT '课程ID',
- CONSTRAINT fk_student_id FOREIGN KEY (student_id) REFERENCES student(id),
- CONSTRAINT fk_course_id FOREIGN KEY (course_id) REFERENCES course(id)
- ) COMMENT = '学生课程关系表';
-
- INSERT INTO student_course VALUES
- (NULL, 1, 1),
- (NULL, 1, 2),
- (NULL, 1, 3),
- (NULL, 2, 2),
- (NULL, 2, 3),
- (NULL, 3, 4);
一对一关系指的是两个表中的一条记录与另一条记录相对应。以下是用户基本信息表和用户教育信息表的示例。
- CREATE TABLE tb_user (
- id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
- name VARCHAR(10) COMMENT '姓名',
- age INT COMMENT '年龄',
- gender CHAR(1) COMMENT '1: 男, 2: 女',
- phone CHAR(11) COMMENT '手机号'
- ) COMMENT = '用户基本信息表';
-
- INSERT INTO tb_user (id, name, age, gender, phone) VALUES
- (NULL, '黄斌', 45, '1', '18800001111'),
- (NULL, '冰冰', 35, '2', '18800002222'),
- (NULL, '码云', 55, '1', '18800008888'),
- (NULL, '李彦宏', 50, '1', '18800009999');
- CREATE TABLE tb_user_edu (
- id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
- degree VARCHAR(20) COMMENT '学历',
- major VARCHAR(50) COMMENT '专业',
- primaryschool VARCHAR(50) COMMENT '小学',
- middleschool VARCHAR(50) COMMENT '中学',
- university VARCHAR(50) COMMENT '大学',
- userid INT UNIQUE COMMENT '用户ID',
- CONSTRAINT fk_userid FOREIGN KEY (userid) REFERENCES tb_user(id)
- ) COMMENT = '用户教育信息表';
-
- INSERT INTO tb_user_edu (id, degree, major, primaryschool, middleschool, university, userid) VALUES
- (NULL, '本科', '舞蹈', '静安区第一小学', '静安区第一中学', '北京舞蹈学院', 1),
- (NULL, '硕士', '表演', '朝阳区第一小学', '朝阳区第一中学', '北京电影学院', 2),
- (NULL, '本科', '英语', '杭州市第一小学', '杭州市第一中学', '杭州师范大学', 3),
- (NULL, '本科', '应用数学', '阳泉区第一小学', '阳泉区第一中学', '清华大学', 4);
多表查询可以分为两大类:连接查询和子查询。
连接查询用于从多个表中提取相关数据,常见的连接类型包括内连接、外连接和自连接。
内连接用于返回两个表中匹配的记录,可以理解为返回两个集合的交集部分。可以通过隐式和显式两种方式实现。
- SELECT emp.name, dept.name
- FROM emp, dept
- WHERE emp.dept_id = dept.id; -- 隐式内连接
- SELECT e.name, d.name
- FROM emp AS e
- INNER JOIN dept AS d ON e.dept_id = d.id; -- 显式内连接
外连接用于返回一个表中的所有记录以及与另一个表中匹配的记录
- SELECT e.*, d.name
- FROM emp e
- LEFT JOIN dept d ON e.dept_id = d.id; -- 左外连接
- SELECT e.*, d.name
- FROM emp e
- RIGHT JOIN dept d ON e.dept_id = d.id; -- 右外连接
自连接是表与自身的连接,通常使用别名来区分
- SELECT e.name, m.name
- FROM emp e
- INNER JOIN emp m ON e.managerid = m.id; -- 自连接
子查询是嵌套在其他查询中的查询,可以分为内查询和外查询。
标量子查询返回单个值,通常用于比较。
- SELECT *
- FROM emp
- WHERE dept_id = (SELECT id FROM dept WHERE name = '销售部'); -- 查询销售部所有员工信息
列子查询返回一列值,通常用于IN条件中。
- SELECT *
- FROM emp
- WHERE dept_id IN (SELECT id FROM dept WHERE name IN ('销售部', '研发部')); -- 查询销售部和研发部所有员工信息
行子查询返回一行值,通常用于比较多列。
- SELECT *
- FROM emp
- WHERE (salary, managerid) = (SELECT salary, managerid FROM emp WHERE name = '张无忌'); -- 查询和张无忌的直属领导工资相同的员工信息
表子查询返回多行值,通常用于JOIN操作中。
- SELECT e.*, d.name AS '部门名称'
- FROM emp e
- INNER JOIN dept d ON e.dept_id = d.id
- WHERE d.name = '研发部'; -- 查询研发部员工信息并显示部门名称
在多表查询中,有一些关键字是非常重要的,以下是一些常用的关键字及其说明:
- SELECT *
- FROM emp
- WHERE salary > ANY (SELECT salary FROM emp WHERE dept_id = (SELECT id FROM dept WHERE name = '研发部'));
- SELECT *
- FROM emp
- WHERE salary > ALL (SELECT salary FROM emp WHERE dept_id = (SELECT id FROM dept WHERE name = '研发部'));
- SELECT * FROM emp WHERE salary < 5000
- UNION
- SELECT * FROM emp WHERE salary > 15000; -- 合并两张表,并过滤条件
- SELECT * FROM emp WHERE salary < 5000
- UNION ALL
- SELECT * FROM emp WHERE salary > 15000; -- 合并两张表,包含重复记录
还有一些 >= > < <= =
多表查询是数据库操作中不可或缺的一部分,通过合理使用连接查询和子查询,能够有效地提取和分析数据。理解多表关系及其查询方式,将有助于更高效地进行数据管理和分析。
下面是所有源码:
-
- -- ---------------------------多表查询------------------------------
-
- -- 多表关系:一对一、一对多、多对多
-
- -- 多对多关系:
- -- 建立第三张表,第三张表中包含两个外键,分别指向两个主表
-
-
- -- 学生表
- CREATE TABLE student (
- id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
- name VARCHAR(10) COMMENT '姓名',
- no VARCHAR(10) COMMENT '学号'
- ) COMMENT = '学生表';
-
- INSERT INTO student (id, name, no) VALUES
- (NULL, '熊绮丝', '2000100101'),
- (NULL, '谢进', '2000100102'),
- (NULL, '殷天正', '2000100103'),
- (NULL, '夷一笑', '2000100104');
-
- -- 课程表
- CREATE TABLE course (
- id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
- name VARCHAR(10) COMMENT '课程名称'
- ) COMMENT = '课程表';
-
- INSERT INTO course (id, name) VALUES
- (NULL, 'Java'),
- (NULL, 'PHP'),
- (NULL, 'MySQL'),
- (NULL, 'Hadoop');
-
- -- 学生课程关系表
- CREATE TABLE student_course (
- id int auto_increment primary key comment '主键ID',
- student_id INT not null COMMENT '学生ID',
- course_id INT not null COMMENT '课程ID',
- constraint fk_student_id foreign key (student_id) references student(id),
- constraint fk_course_id foreign key (course_id) references course(id)
- ) COMMENT = '学生课程表';
-
- insert into student_course values(null, 1, 1),(null, 1, 2),(null, 1, 3),(null, 2, 2),(null, 2, 3),(null, 3, 4);
-
- -- 一对一关系
-
- create table tb_user (
- id int auto_increment primary key comment '主键ID',
- name varchar(10) comment '姓名',
- age int comment '年龄',
- gender char(1) comment '1: 男, 2: 女',
- phone char(11) comment '手机号'
- ) comment = '用户基本信息表';
-
-
- create table tb_user_edu (
- id int auto_increment primary key comment '主键ID',
- degree varchar(20) comment '学历',
- major varchar(50) comment '专业',
- primaryschool varchar(50) comment '小学',
- middleschool varchar(50) comment '中学',
- university varchar(50) comment '大学',
- userid int unique comment '用户ID',
- constraint fk_userid foreign key (userid) references tb_user(id)
- ) comment = '用户教育信息表';
-
- insert into tb_user (id, name, age, gender, phone) values
- (null, '黄斌', 45, '1', '18800001111'),
- (null, '冰冰', 35, '2', '18800002222'),
- (null, '码云', 55, '1', '18800008888'),
- (null, '李彦宏', 50, '1', '18800009999');
-
- insert into tb_user_edu (id, degree, major, primaryschool, middleschool, university, userid) values
- (null, '本科', '舞蹈', '静安区第一小学', '静安区第一中学', '北京舞蹈学院', 1),
- (null, '硕士', '表演', '朝阳区第一小学', '朝阳区第一中学', '北京电影学院', 2),
- (null, '本科', '英语', '杭州市第一小学', '杭州市第一中学', '杭州师范大学', 3),
- (null, '本科', '应用数学', '阳泉区第一小学', '阳泉区第一中学', '清华大学', 4);
-
-
- -- 多表查询
-
- -- 多表查询分类 :连接查询、子查询
-
- -- 连接查询:
- -- 内连接:
- # 隐式内连接:select * from 表1,表2 where 表1.字段 = 表2.字段;
- # 显式内连接:select * from 表1 inner join 表2 on 表1.字段 = 表2.字段;
-
-
- select * from emp,dept where emp.dept_id = dept.id; -- 消除笛卡尔积,重复数据
-
- -- 查询员工的姓名和所属部门的名称
- select emp.name, dept.name from emp,dept where emp.dept_id = dept.id; -- 隐式内连接
- select e.name, d.name from emp as e,dept as d where e.dept_id = d.id; -- 别名隐式连接
-
- select e.name, d.name from emp as e inner join dept as d on e.dept_id = d.id; -- 显式内连接
-
-
- -- 外连接:select * from 表1 left join 表2 on 表1.字段 = 表2.字段;
- -- 左外连接:select * from 表1 left join 表2 on 表1.字段 = 表2.字段;
- -- 右外连接:select * from 表1 right join 表2 on 表1.字段 = 表2.字段;
-
- select e.*, d.name from emp e left outer join dept d on e.dept_id = d.id; -- 左外连接
- select e.*, d.name from emp e right outer join dept d on e.dept_id = d.id; -- 右外连接
-
-
- -- 自连接:当前表与自身的连接查询,必须使用别名
- # 自连接查询:select * from 表1 as t1 join 表1 as t2 on t1.字段 = t2.字段;
- # 自连接查询:select * from 表1 as t1 inner join 表1 as t2 on t1.字段 = t2.字段;
- select e.name, m.name from emp e ,emp m where e.managerid = m.id; -- 自连接
- select e.name as '员工姓名', m.name as '直属领导姓名' from emp e inner join emp m on m.id = e.managerid; -- 自连接
-
-
- -- 联合查询:查询多个表的数据,并将多个表的数据合并成一张表
-
- #注意区分 union 和 union all 的区别,union 去重,union all 不去重
-
- select * from emp where salary < 5000 union select * from emp where salary > 15000; -- 合并两张表,并过滤条件
-
-
- -- 子查询:
- -- 内查询:select * from 表1 where 字段 in (select 字段 from 表2);
- -- 外查询:select * from 表1 where 字段 in (select 字段 from 表2 where 条件);
- -- 子查询:select * from 表1 where 字段 in (select 字段 from 表2 where 条件);
-
- # 标量子查询 列子查询 行子查询 表子查询
-
- -- 标量子查询:查询单个值
- select * from emp where dept_id = (select id from dept where name = '销售部'); -- 销售部所有员工信息
-
- -- 列子查询:查询一列值
- select * from emp where dept_id in (select id from dept where name in ('销售部','研发部')); -- 销售部和研发部所有员工信息
- # 查询比研发部任意一个员工工资高的员工信息
- select * from emp where salary > any (select salary from emp where dept_id = (select id from dept where name = '研发部'));
- # 查询比研发部所有员工工资高的员工信息
- select * from emp where salary > all (select salary from emp where dept_id = (select id from dept where name = '研发部'));
-
- -- 行子查询:查询一行值
- #和张无忌的直属领导,工资相同的员工信息
- select * from emp where (salary,managerid) = (select salary,managerid from emp where name = '张无忌');
-
- -- 表子查询:查询多行值
- # 查询部门为研发部的员工信息
- select * from emp where dept_id = (select id from dept where name = '研发部');
- # 查询部门为研发部的员工信息,并显示员工的部门名称
- select e.*, d.name as '部门名称' from emp e inner join dept d on e.dept_id = d.id where d.name = '研发部';
- # 查询部门为研发部的员工信息,并显示员工的部门名称,并显示员工的直属领导姓名
- select e.*, d.name as '部门名称', m.name as '直属领导姓名' from emp e inner join dept d on e.dept_id = d.id inner join emp m on e.managerid = m.id where d.name = '研发部';
最后制作不易,点赞支持一下吧……
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。