day02——1.多表关系

本文详细介绍了数据库设计中的三种基本关系:一对一、一对多和多对多,并通过实例展示了如何创建和管理这些关系的表。同时,讨论了内连接、外连接和子查询在多表查询中的应用,提供了具体的SQL示例,帮助理解如何在实际项目中优化数据操作。
摘要由CSDN通过智能技术生成

多表关系

在实际项目开发的时候可能设计到多张表,表与表之间存在一定关系,如何设计表之间的关系让系统更加优化,需要考虑到多表之间关系。

1. 一对一(了解)
	* 如:人和身份证
	* 分析:一个人只有一个身份证,一个身份证只能对应一个人
2. 一对多(多对一)
	* 如:部门和员工
	* 分析:一个部门有多个员工,一个员工只能对应一个部门
3. 多对多
	* 如:学生和课程
	* 分析:一个学生可以选择很多门课程,一个课程也可以被很多学生选择

一对一关系

一个人有一个身份证号码,一个身份证号码只对应一个人

在这里插入图片描述

-- 创建身份证表
CREATE TABLE card(
	id INT PRIMARY KEY,
	number VARCHAR(18)
);
-- 设置身份证号码唯一
ALTER TABLE card MODIFY number VARCHAR(20) UNIQUE;

INSERT INTO card(id,number) VALUES(1,420923199211090512);
INSERT INTO card(id,number) VALUES(2,420923199310230807);
INSERT INTO card(id,number) VALUES(3,420923199007080908);

-- 创建人员表
CREATE TABLE person(
	id INT PRIMARY KEY,
	NAME VARCHAR(20),
	cid INT
);
-- 给人员表添加外键
ALTER TABLE person ADD CONSTRAINT cid_kf FOREIGN KEY(cid) REFERENCES card(id);
-- 设置外键唯一
ALTER TABLE person MODIFY cid INT UNIQUE;
-- 向person表中添加数据
INSERT INTO person(id,NAME,cid) VALUES(1,"张三",1);
INSERT INTO person(id,NAME,cid) VALUES(2,"李四",2);
INSERT INTO person(id,NAME,cid) VALUES(3,"王五",3);

一对多关系

一个部门可以有多个员工,一个员工只能对应一个部门

在这里插入图片描述

-- 创建部门表(主表)
CREATE TABLE department(
	id INT PRIMARY KEY,
	NAME VARCHAR(20)
);
-- 向部门表中添加数据
INSERT INTO department(id,NAME) VALUES(1,"教研部");
INSERT INTO department(id,NAME) VALUES(2,"学工部");
INSERT INTO department(id,NAME) VALUES(3,"就业部");

SELECT * FROM department;

-- 创建员工表(从表)
CREATE TABLE employee(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20) NOT NULL,
	age INT,
	dep_id INT,
	CONSTRAINT emp_depid_fk FOREIGN KEY(dep_id) REFERENCES department(id)
);
-- 向员工表中添加数据
INSERT INTO employee(NAME,age,dep_id) VALUES("张三",18,1);
INSERT INTO employee(NAME,age,dep_id) VALUES("李四",20,2);
INSERT INTO employee(NAME,age,dep_id) VALUES("王五",21,1);
INSERT INTO employee(NAME,age,dep_id) VALUES("赵六",19,3);
INSERT INTO employee(NAME,age,dep_id) VALUES("田七",24,2);
INSERT INTO employee(NAME,age,dep_id) VALUES("周八",23,3);
INSERT INTO employee(NAME,age,dep_id) VALUES("黄九",25,1);

SELECT * FROM employee;

多对多关系

一个学生可以选择很多门课程,一个课程也可以被很多学生选择

在这里插入图片描述

-- 创建学生表
CREATE TABLE student(
	sid INT PRIMARY KEY,
	NAME VARCHAR(20),
	age INT
);
INSERT INTO student(sid,NAME,age) VALUES(1,"张三",20);
INSERT INTO student(sid,NAME,age) VALUES(2,"李四",19);
INSERT INTO student(sid,NAME,age) VALUES(3,"王五",18);
INSERT INTO student(sid,NAME,age) VALUES(4,"赵六",21);
INSERT INTO student(sid,NAME,age) VALUES(5,"田七",24);
INSERT INTO student(sid,NAME,age) VALUES(6,"周八",23);

-- 创建课程表
CREATE TABLE class(
	cid INT PRIMARY KEY,
	NAME VARCHAR(20)
);
INSERT INTO class(cid,NAME) VALUES(1,"Java基础");
INSERT INTO class(cid,NAME) VALUES(2,"HTML");
INSERT INTO class(cid,NAME) VALUES(3,"Javascript");
INSERT INTO class(cid,NAME) VALUES(4,"mysql");


-- 创建外键表
CREATE TABLE foreign_table(
	sid INT,
	cid INT,
	CONSTRAINT sid_fk FOREIGN KEY(sid) REFERENCES student(sid), -- 外键sid 关联 student sid主键
	CONSTRAINT cid_fk FOREIGN KEY(cid) REFERENCES class(cid)   -- 外键cid 关联 class cid主键
);
INSERT INTO foreign_table(sid,cid) VALUES(1,1);
INSERT INTO foreign_table(sid,cid) VALUES(1,2);
INSERT INTO foreign_table(sid,cid) VALUES(1,3);
INSERT INTO foreign_table(sid,cid) VALUES(1,4);
INSERT INTO foreign_table(sid,cid) VALUES(2,1);
INSERT INTO foreign_table(sid,cid) VALUES(2,2);
INSERT INTO foreign_table(sid,cid) VALUES(3,4);
INSERT INTO foreign_table(sid,cid) VALUES(3,1);

多表查询

准备数据

-- 创建db4数据库
CREATE DATABASE db4;
-- 使用db4数据库
USE db4;

-- 创建user表
CREATE TABLE USER(
	id INT PRIMARY KEY AUTO_INCREMENT,	-- 用户id
	NAME VARCHAR(20),			-- 用户姓名
	age INT                                 -- 用户年龄
);
-- 添加数据
INSERT INTO USER VALUES (1,'张三',23);
INSERT INTO USER VALUES (2,'李四',24);
INSERT INTO USER VALUES (3,'王五',25);
INSERT INTO USER VALUES (4,'赵六',26);


-- 订单表
CREATE TABLE orderlist(
	id INT PRIMARY KEY AUTO_INCREMENT,	-- 订单id
	number VARCHAR(30),			-- 订单编号
	uid INT,    -- 外键字段
	CONSTRAINT ou_fk1 FOREIGN KEY (uid) REFERENCES USER(id)
);
-- 添加数据
INSERT INTO orderlist VALUES (1,'hm001',1);
INSERT INTO orderlist VALUES (2,'hm002',1);
INSERT INTO orderlist VALUES (3,'hm003',2);
INSERT INTO orderlist VALUES (4,'hm004',2);
INSERT INTO orderlist VALUES (5,'hm005',3);
INSERT INTO orderlist VALUES (6,'hm006',3);
INSERT INTO orderlist VALUES (7,'hm007',NULL);


-- 商品分类表
CREATE TABLE category(
	id INT PRIMARY KEY AUTO_INCREMENT,  -- 商品分类id
	NAME VARCHAR(10)                    -- 商品分类名称
);
-- 添加数据
INSERT INTO category VALUES (1,'手机数码');
INSERT INTO category VALUES (2,'电脑办公');
INSERT INTO category VALUES (3,'烟酒茶糖');
INSERT INTO category VALUES (4,'鞋靴箱包');


-- 商品表
CREATE TABLE product(
	id INT PRIMARY KEY AUTO_INCREMENT,   -- 商品id
	NAME VARCHAR(30),                    -- 商品名称
	cid INT, -- 外键字段
	CONSTRAINT cp_fk1 FOREIGN KEY (cid) REFERENCES category(id)
);
-- 添加数据
INSERT INTO product VALUES (1,'华为手机',1);
INSERT INTO product VALUES (2,'小米手机',1);
INSERT INTO product VALUES (3,'联想电脑',2);
INSERT INTO product VALUES (4,'苹果电脑',2);
INSERT INTO product VALUES (5,'中华香烟',3);
INSERT INTO product VALUES (6,'玉溪香烟',3);
INSERT INTO product VALUES (7,'计生用品',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);
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);

内连接查询

  • 内连接查询语法
-- 显示内连接查询
SELECT 列名 FROM 表名1 [INNER] JOIN 表名2 ON 关联条件;

-- 隐式内连接查询
SELECT 列名 FROM 表名1,表名2 WHERE 关联条件;
  • 内连接查询举例
-- 查询用户信息和对应的订单信息

-- 查询用户信息和对应的订单信息,起别名

-- 查询用户姓名,年龄。和订单编号

外连接查询

  • 外连接查询语法
-- 左外连接查询
SELECT 列名 FROM 表名1 LEFT [OUTER] JOIN 表名2 ON 条件;

-- 右外连接查询
SELECT 列名 FROM 表名1 RIGHT [OUTER] JOIN 表名2 ON 条件;
  • 外连接查询举例
-- 查询所有用户信息,以及用户对应的订单信息
SELECT
	u.*,
	o.number
FROM
	USER u
	LEFT OUTER JOIN
	orderlist o
ON
	o.uid=u.id;

-- 查询所有订单信息,以及订单所属的用户信息
SELECT
	u.*,
	o.number
FROM
	USER u
	RIGHT OUTER JOIN
	orderlist o
ON
	o.uid=u.id;

子查询

子查询就是利用SQL语句的查询结果,再结合其他SQL条件再次进行查询。

  • 子查询的结果是一行一列

子查询的结果是一行一列,可以将子查询的结果当做某一个字段的值,作为where子句的条件;

-- 查询用户最大的年龄
SELECT MAX(age) FROM USER;

-- 查询年龄最大的用户姓名
select name ,age from user where age=(select max(age) from user);
  • 子查询的结果是多行单列

子查询的结果是多行单列,可以将子查询的结果当做某一个字段的多个值,作为where子句的条件。

-- 查询张三和李四的id
select id from user where name in('张三','李四');

-- 查询张三和李四的订单信息
select * from orderlist where uid in (select id from user where name in('张三','李 四'));
  • 子查询的结果是多行多列

子查询的结果是多行多列,可以将子查询的结果当做一个表来看待,并和其他表进行连接查询。

-- 查询订单表中id>4的订单信息
select * from orderlist where id>4;

-- 查询订单表中id大于4的订单信息和所属用户信息
select u.name,o.number from user u ,(select * from orderlist where id>4) o where o.uid=u.id;

自关联查询

  • 准备数据
-- 创建员工表
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.mgr = employee.id
	查询左表的全部数据,和左右两张表有交集部分数据,左外连接
*/
SELECT
	e1.id,
	e1.name,
	e1.mgr,
	e2.id,
	e2.name
FROM
	employee e1
LEFT OUTER JOIN
	employee e2
ON
	e1.mgr = e2.id;

多表查询练习

  1. 查询用户的编号、姓名、年龄。订单编号
/*
分析:
	查询的表:用户表(user),订单表(orderlist)
	查询的字段:用户编号,姓名,年龄,订单编号
	查询的条件:user.id=orderlist.uid
*/

select
	u.id,u.name,u.age,o.number
from 
	user u,orderlist o
where 
	u.id=o.uid;
  1. 查询所有的用户。用户的编号、姓名、年龄。订单编号
/*
分析:
	查询的表:用户表(user),订单表(orderlist)。 所有用户,左外连接
	查询的字段:用户编号,姓名,年龄,订单编号
	查询的条件:orderlist.uid = user.id
*/

select 
	u.id,u.name,u.age,o.number
from 
	user u 
left join
	orderlist o 
on
	u.id=o.uid;
  1. 查询所有的订单。用户的编号、姓名、年龄。订单编号
/*
分析:
	查询的表:用户表(user),订单表(orderlist)。所有订单,忧外连接
	查询的字段:用户的编号、姓名、年龄、订单编号
	查询的条件:orderlist.uid = user.id
*/

select 
	u.id,u.name,u.age,o.number
from 
	user u 
right join
	orderlist o
on 
	o.uid=u.id;
  1. 查询用户年龄大于23岁的信息。显示用户的编号、姓名、年龄。订单编号
/*
分析:
	查询的表:用户表(user),订单表(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;
  1. 查询张三和李四用户的信息。显示用户的编号、姓名、年龄。订单编号
/*
分析:
	查询的表:用户表(user),订单表(orderlist)
	查询的字段:显示用户的编号、姓名、年龄。订单编号
	查询的条件:user.name in ("张三","李四") and user.id=orderlist.uid;
*/

select 
	u.id,u.name,u.age,o.number
from 
	user u,
	orderlist o
where 
	u.id=o.uid and u.name in ("张三","李四");
  1. 查询商品分类的编号、分类名称。分类下的商品名称
/*
分析:
	查询的表:商品表(product)、分类表(category)
	查询的字段:商品分类的编号、分类名称、商品名称
	查询的条件:product.cid=category.id
*/

select 
	c.id,c.name,p.name
from 
	product p,
	category c
where 
	p.cid=c.id;
  1. 查询所有的商品分类。商品分类的编号、分类名称。分类下的商品名称
/*
分析:
	查询的表:商品表(product)、分类表(category)
	查询的字段:商品分类的编号(id)、分类名称(name)、商品名称(name)
	查询的条件:product.cid=category.id
*/

select 
	c.id,c.name,p.name
from 
	product p 
right join
	category c
on 
	p.cid=c.id;
  1. 查询所有的商品信息。商品分类的编号、分类名称。分类下的商品名称
/*
分析:
	查询的表:商品表(product)、分类表(category)
	查询的字段:商品分类的编号(id)、分类名称(name)、商品名称(name)
	查询的条件:product.cid=category.id
*/

select 
	c.id,c.name,p.name
from 
	product p 
left join
	category c
on 
	p.cid=c.id;
  1. 查询所有的用户和该用户能查看的所有的商品。显示用户的编号、姓名、年龄。商品名称
/*
分析:
	查询的表:用户表(user),商品表(product),中间表(us_pro)
	查询的字段:用户的编号、姓名、年龄。商品名称
	查询的条件:user.id=us_pro.uid and product.id=us_pro.pid;
*/

select 
	u.id,u.name,u.age,p.name
from 
	user u,
	product p,
	us_pro up
where 
	u.id=up.uid and p.id=up.pid;
  1. 查询张三和李四这两个用户可以看到的商品。显示用户的编号、姓名、年龄。商品名称
/*
分析:
	查询的表:用户表(user),商品表(product),中间表(us_pro)
	查询的字段:用户的编号、姓名、年龄。商品名称
	查询的条件:
		user.name in ("张三","李四")
        and 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 
	u.name in ("张三","李四") and up.uid=u.id and up.pid=p.id;
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值