LINUX-MySQL多表查询

1.多表查询概念

用途:每张表都有一些信息,需要将它们整合起来查看

2.连接类型

|------|------------|----------------------|
| 连接类型 | 关键字 | 描述 |
| 内连接 | INNER JOIN | 取两表交集(只显示能找到匹配项的记录) |
| 左连接 | LEFT JOIN | 左表为主表,右表为从表(左核心,右补充) |
| 右连接 | RIGHT JOIN | 右表为主表,左表为从表(右核心,左补充) |
| 全连接 | FULL JOIN | 取两表并集(全部显示) |
| 交叉连接 | CROSS JOIN | 排列组合(不常用) |
[连接类型]

3.示例表结构

复制代码
-- 部门表
CREATE TABLE departments (
    dept_id INT PRIMARY KEY,
    dept_name VARCHAR(50)
);

-- 员工表
CREATE TABLE employees (
    emp_id INT PRIMARY KEY,
    emp_name VARCHAR(50),
    dept_id INT, -- 外键,关联departments表
    salary DECIMAL(10, 2)
);

-- 项目表 (用于演示多对多)
CREATE TABLE projects (
    project_id INT PRIMARY KEY,
    project_name VARCHAR(50)
);

-- 员工-项目关联表
CREATE TABLE emp_project (
    emp_id INT,
    project_id INT,
    PRIMARY KEY (emp_id, project_id)
);

INSERT INTO departments VALUES (1, '研发部'), (2, '市场部'), (3, '财务部');

INSERT INTO employees VALUES
(1, '张三', 1, 10000),
(2, '李四', 1, 12000),
(3, '王五', 2, 8000),
(4, '赵六', NULL, 9000); -- 注意:赵六没有部门

INSERT INTO projects VALUES (101, '项目A'), (102, '项目B');

INSERT INTO emp_project VALUES (1, 101), (1, 102), (2, 101), (3, 102);

4.查询示范

4.1内连接

SELECT a.字段名 b.字段名 FROM 表1 a INNER JOIN 表2 b ON a.共有字段名 = b.共有字段名;(其中a与b为表别名)

示例:查询每个员工姓名及其部门名称。
复制代码
SELECT e.emp_name,d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id = d.dept_id;

没有赵六,因为他的dept_id是NULL,在departments表找不到匹配项。

4.2左连接

SELECT a.字段名 b.字段名 FROM 表1 a LEFT JOIN 表2 b ON a.共有字段名 = b.共有字段名;(其中a与b为表别名)

示例:查询所有员工姓名及其部门名称(包括没有部门的员工)。
复制代码
SELECT e.emp_name,d.dept_name FROM employees e LEFT JOIN departments d ON e.dept_id = d.dept_id;

4.3右连接

SELECT a.字段名 b.字段名 FROM 表1 a RIGHT JOIN 表2 b ON a.共有字段名 = b.共有字段名;(其中a与b为表别名)

示例:查询所有部门及其员工信息(包括没有员工的部门)。
复制代码
SELECT e.emp_name,d.dept_name FROM employees e RIGHT JOIN departments d ON e.dept_id = d.dept_id;

4.4多表连接与表别名

示例:查询每个员工的名字、部门名称以及他参与的项目名称。
复制代码
 SELECT e.emp_name,d.dept_name,p.project_name FROM employees e LEFT JOIN departments d ON e.dept_id = d.dept_id INNER JOIN emp_project ep ON ep.emp_id = e.emp_id INNER JOIN projects p ON p.project_id = ep.project_id;

5.联合查询

作用 :合并多个SELECT语句的结果集。

要求:列数、数据类型必须相同或兼容。
注意: UNION vs UNION ALL:UNION会去重,UNION ALL不去重,性能更高。

示例:查询所有部门名字和员工的名字,合并成一个列表。
复制代码
SELECT dept_name FROM departments UNION SELECT emp_name FROM employees;

6.全连接

实质:左/右连接 UNION 左/右连接(UNION左右互相取对立)

示例:查询所有部门名字和员工的名字
复制代码
select e.emp_name,d.dept_name from employees e left join departments d on e.dept_id=d.dept_id union select e.emp_name,d.dept_name from employees e right join departments d on e.dept_id=d.dept_id;

7.例题一(双表查询)

7.1数据准备

复制代码
表一
create database company;

create table employee6( emp_id int auto_increment primary key, emp_name varchar(50), age int, dept_id int);

desc employee6;

insert into employee6(emp_name,age,dept_id) values('xiaoli',19,200),('tom',26,201),('jack',30,201),('alice',24,202),('robin',40,200),('zhangsan',28,204);

select * from employee6;

表二
create table department6(dept_id int, dept_name varchar(100));

desc department6;

insert into department6 values
(200,'hr'),
(201,'it'),
(202,'sale'),
(203,'op');

select * from department6;

7.2问题

7.2.1只找出有相同部门的员工

复制代码
SELECT e.emp_name,d.dept_name FROM employee6 e INNER JOIN department6 d ON e.dept_id = d.dept_id;

7.2.2查找出所有员工及所属部门

复制代码
SELECT e.emp_name,IFNULL(d.dept_name,'暂无部门') FROM employee6 e LEFT JOININ department6 d ON e.dept_id = d.dept_id;

7.2.3找出所有部门包含的员工

复制代码
SELECT IFNULL(e.emp_name,'暂无员工'),d.dept_name FROM employee6 e RIGHT JOINOIN department6 d ON e.dept_id = d.dept_id;

7.2.4找出所有部门包含的员工,所有员工所属的部门名称

复制代码
SELECT IFNULL(e.emp_name,'暂无员工'),IFNULL(d.dept_name,'暂无部门') FROM employee6 e RIGHT JOIN department6 d ON e.dept_id = d.dept_id UNION SELECT e.emp_name,IFNULe,'暂无L(d.dept_name,'暂无部

8.例题二(三表查询)

8.1数据准备

复制代码
--表一:用户表(主表)
CREATE TABLE users (
    user_id INT PRIMARY KEY AUTO_INCREMENT,  -- 用户ID,主键
    username VARCHAR(50) NOT NULL,           -- 用户名
    email VARCHAR(100) NOT NULL UNIQUE       -- 邮箱
);

--表二:分类表(主表)
CREATE TABLE categories (
    category_id INT PRIMARY KEY AUTO_INCREMENT, -- 分类ID,主键
    category_name VARCHAR(50) NOT NULL UNIQUE   -- 分类名
);


--表三:文章表(关联表,包含两外键)
CREATE TABLE articles (
    article_id INT PRIMARY KEY AUTO_INCREMENT,    -- 文章ID,主键
    title VARCHAR(200) NOT NULL,                  -- 文章标题
    content TEXT,                                 -- 文章内容
    user_id INT,                                  -- 外键:关联用户表 (文章作者)
    category_id INT,                              -- 外键:关联分类表 (文章分类)
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 创建时间
    -- 定义外键约束(可选,但强烈建议,用于保证数据完整性)
    FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE SET NULL,
    FOREIGN KEY (category_id) REFERENCES categories(category_id) ON DELETE SET NULL
);

--插入数据
INSERT INTO users (username, email) VALUES
('张三', 'zhangsan@email.com'),
('李四', 'lisi@email.com'),
('王五', 'wangwu@email.com');

INSERT INTO categories (category_name) VALUES
('技术'),
('生活'),
('旅游');

INSERT INTO articles (title, content, user_id, category_id) VALUES
('MySQL入门教程', '...正文内容...', 1, 1), -- 张三写了技术文章
('Python编程技巧', '...正文内容...', 1, 1), -- 张三写了技术文章
('我的周末生活', '...正文内容...', 2, 2), -- 李四写了生活文章
('西藏之旅', '...正文内容...', 3, 3);     -- 王五写了旅游文章

insert into users values(4,'NATASHA','NATASHA@163.com');

8.2问题

8.2.1查询所有文章的详细信息,包括作者名分类名。(只查有作者且有分类的文章)

复制代码
SELECT u.username,a.title,category_name FROM users u INNER JOIN articlesa ON a.user_id = u.user_id INNER JOIN categories c ON c.category_id = a.category_id;

8.2.2查询所有用户及其发表的文章和分类(即使用户没写文章也要显示)

复制代码
SELECT u.username,IFNULL(a.title,'暂无文章'),IFNULL(c.category_name,'暂无分类') FROM users u LEFT JOIN articles a ON u.user_id = a.user_id LEFT JOIN categgories c ON a.category_id = c.category_id;

8.2.3查询所有分类下都有哪些文章,由谁所写(即使分类下没有文章也要显示)。

复制代码
SELECT IFNULL(c.category_name,'玄幻'),IFNULL(a.title,'暂无文章'),u.username FROMme FROM categories c LEFT JOIN articles a ON c.category_id = a.category_id RIGHT  JOIN users u On u.user_id = a.user_id;

8.2.4统计每个分类下的文章数量。

复制代码
SELECT c.category_name,COUNT(a.article_id) FROM categories c LEFT JOIN articles a ON c.category_id = a.category_id GROUP BY c.category_id;
相关推荐
a***592610 小时前
MySQL数据可视化实战指南
数据库·mysql·信息可视化
lxp19974110 小时前
Mysql短课题全手稿
数据库·mysql
我是一只小青蛙88810 小时前
Python实战:Kingbase数据库高效操作指南
数据库·oracle
龙亘川10 小时前
【课程5.7】代码编写:违建处置指标计算(违建发现率、整改率SQL实现)
数据库·oracle·智慧城市·一网统管平台
松涛和鸣10 小时前
55、ARM与IMX6ULL入门
c语言·arm开发·数据库·单片机·sqlite·html
这儿有一堆花10 小时前
Linux 内网环境构建与配置深度解析
linux·数据库·php
Codeking__10 小时前
Redis——事务
数据库·redis·缓存
Codeking__11 小时前
Redis——认识持久化、RDB、AOF
数据库·redis·缓存
Funky_oaNiu11 小时前
Oracle在没有dba权限和表空间对不上和不能用数据泵的情况下迁移
数据库·oracle·dba