SQL多表操作与视图

1.多表关系

1.表与表之间的联系

1. 一对一:
            如:人和身份证
            分析:一个人只有一个身份证,一个身份证只能对应一个人

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

           一般会建立第三张表,至少包含两个外键,分别指向两张表的主键

2.实现联系

1. 一对多(多对一):
            如:部门和员工
            实现方式:在多的一方建立外键,指向一的一方的主键。
2. 多对多:
            如:学生和课程
            实现方式:多对多关系实现需要借助第三张中间表。中间表至少包含两个字段,这两个字段作为第三张表的外键,分别指向两张表的主键
3. 一对一(了解):
            如:人和身份证
            实现方式:一对一关系实现,可以在任意一方添加唯一外键指向另一方的主键。

笛卡尔积:
笛卡尔积为两个集合(两张表)中的每条数据进行两两组合的结果
在多表查询时会产生笛卡尔积,要通过添加条件消除笛卡尔积

查询产生笛卡尔积的结果:

select * from emp, dept ;

消除笛卡尔积(添加条件):

select * from emp, dept where emp.dept_id=dept.id;

2.多表查询

内连接

                相当于查询AB的交集部分

外连接

                左外连接: 查询A的所有数据,同时拼接上B对应的数据

                右外连接: 查询B的所有数据,同时拼接上A中对应的数据

子查询:

                查询中嵌套查询,称嵌套查询为子查询。

自连接

                 表与自身连接查询 自连接必须给表取别名

1.数据准备

	# 创建部门表
	CREATE TABLE dept(
		id INT PRIMARY KEY AUTO_INCREMENT,
		NAME VARCHAR(20)
	);
	INSERT INTO dept (NAME) VALUES ('开发部'),('市场部'),('财务部');
	# 创建员工表
	CREATE TABLE emp (
		id INT PRIMARY KEY AUTO_INCREMENT,
		NAME VARCHAR(10),
		gender CHAR(1), -- 性别
		salary DOUBLE, -- 工资
		join_date DATE, -- 入职日期
		dept_id INT,
		FOREIGN KEY (dept_id) REFERENCES dept(id) -- 外键,关联部门表(部门表的主键)
	);
	INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('孙悟空','男',7200,'2013-02-24',1);
	INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('猪八戒','男',3600,'2010-12-02',2);
	INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('唐僧','男',9000,'2008-08-08',2);
	INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('白骨精','女',5000,'2015-10-07',3);
	INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('蜘蛛精','女',4500,'2011-03-14',1);

2.内连接查询

1.隐式内连接:使用where条件消除无用数据

语法:

select 字段列表 from 表1,表2 where 筛选条件 ;

例:

-- 查询所有员工信息和对应的部门信息

	SELECT * FROM emp,dept WHERE emp.`dept_id` = dept.`id`;

查询员工表的名称,性别。部门表的名称 

SELECT emp.name,emp.gender,dept.name FROM emp,dept WHERE emp.`dept_id` = dept.`id`;
SELECT 
	    t1.name, -- 员工表的姓名
		t1.gender,-- 员工表的性别
		t2.name -- 部门表的名称
	FROM
		emp t1,
		dept t2
	WHERE 
		t1.`dept_id` = t2.`id`;

 2.显式内连接

语法:

select 字段列表 from 表名1 [inner] join 表名2 on 条件

例: 

	SELECT * FROM emp INNER JOIN dept ON emp.`dept_id` = dept.`id`;	
	SELECT * FROM emp JOIN dept ON emp.`dept_id` = dept.`id`;	

2.外连接查询

在这里插入图片描述

 1.左外连接

左外连接相当于查询表A(左表)的所有数据和中间绿色的交集部分的数据。

语法:

select 字段列表 from 表1 left [outer] join 表2 on 条件;

例子:

查询所有员工信息,如果员工有部门,则查询部门名称,没有部门,则不显示部门名称

SELECT 	t1.*,t2.`name` FROM emp t1 LEFT JOIN dept t2 ON t1.`dept_id` = t2.`id`;

3.右外连接

右外连接相当于查询表B(右表)的所有数据和中间绿色的交集部分的数据。

语法:

select 字段列表 from 表1 right [outer] join 表2 on 条件;

例:

SELECT 	* FROM dept t2 RIGHT JOIN emp t1 ON t1.`dept_id` = t2.`id`;

 3.子查询

    -- 查询工资最高的员工信息
	-- 1 查询最高的工资是多少 9000
	SELECT MAX(salary) FROM emp;
			
	-- 2 查询员工信息,并且工资等于9000的
	SELECT * FROM emp WHERE emp.`salary` = 9000;
			
	-- 一条sql就完成这个操作。子查询
	SELECT * FROM emp WHERE emp.`salary` = (SELECT MAX(salary) FROM emp);

1. 子查询的结果是单行单列的:

子查询可以作为条件,使用运算符去判断。 运算符: > >= < <= =

-- 查询员工工资小于平均工资的人
		SELECT * FROM emp WHERE emp.salary < (SELECT AVG(salary) FROM emp);

2. 子查询的结果是多行单列的:

子查询可以作为条件,使用运算符in来判断

-- 查询'财务部'和'市场部'所有的员工信息
		SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部';
		SELECT * FROM emp WHERE dept_id = 3 OR dept_id = 2;
-- 子查询
		SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部');

3. 子查询的结果是多行多列的:

子查询可以作为一张虚拟表参与查询

-- 子查询
		SELECT * FROM dept t1 ,(SELECT * FROM emp WHERE emp.`join_date` > '2011-11-11') t2
		WHERE t1.id = t2.dept_id;
				
-- 普通内连接
		SELECT * FROM emp t1,dept t2 WHERE t1.`dept_id` = t2.`id` AND t1.`join_date` >  '2011-11-11'

4.自连接查询

语法:

select 字段列表 from 表a 别名a join 表a 别名b on 条件;

自链接查询可以是内连接查询也可以是外连接查询

3.多表查询案例

数据准备

-- 部门表
	CREATE TABLE dept (
	  id INT PRIMARY KEY PRIMARY KEY, -- 部门id
	  dname VARCHAR(50), -- 部门名称
	  loc VARCHAR(50) -- 部门所在地
	);
			
-- 添加4个部门
	INSERT INTO dept(id,dname,loc) VALUES 
	(10,'教研部','北京'),
	(20,'学工部','上海'),
	(30,'销售部','广州'),
	(40,'财务部','深圳');
-- 职务表,职务名称,职务描述
	CREATE TABLE job (
	  id INT PRIMARY KEY,
	  jname VARCHAR(20),
	  description VARCHAR(50)
	);
			
-- 添加4个职务
	INSERT INTO job (id, jname, description) VALUES
	(1, '董事长', '管理整个公司,接单'),
	(2, '经理', '管理部门员工'),
	(3, '销售员', '向客人推销产品'),
	(4, '文员', '使用办公软件');
-- 员工表
	CREATE TABLE emp (
	  id INT PRIMARY KEY, -- 员工id
	  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 INT -- 最高工资
	);
			
-- 添加5个工资等级
	INSERT INTO salarygrade(grade,losalary,hisalary) VALUES 
	(1,7000,12000),
	(2,12010,14000),
	(3,14010,20000),
	(4,20010,30000),
	(5,30010,99990);

1.查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述

/*
	分析:
		1.员工编号,员工姓名,工资,需要查询emp表  职务名称,职务描述 需要查询job表
		2.查询条件 emp.job_id = job.id
			
*/
	SELECT 
		t1.`id`, -- 员工编号
		t1.`ename`, -- 员工姓名
		t1.`salary`,-- 工资
		t2.`jname`, -- 职务名称
		t2.`description` -- 职务描述
	FROM 
		emp t1, job t2
	WHERE 
		t1.`job_id` = t2.`id`;

2.查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置

/*
	分析:
		1. 员工编号,员工姓名,工资 emp  职务名称,职务描述 job  部门名称,部门位置 dept
		2. 条件: emp.job_id = job.id and emp.dept_id = dept.id
*/
			
	SELECT 
		t1.`id`, -- 员工编号
		t1.`ename`, -- 员工姓名
		t1.`salary`,-- 工资
		t2.`jname`, -- 职务名称
		t2.`description`, -- 职务描述
		t3.`dname`, -- 部门名称
		t3.`loc` -- 部门位置
	FROM 
		emp t1, job t2,dept t3
	WHERE 
		t1.`job_id` = t2.`id` AND t1.`dept_id` = t3.`id`;

3.查询员工姓名,工资,工资等级

/*
	分析:
		1.员工姓名,工资 emp  工资等级 salarygrade
		2.条件 emp.salary >= salarygrade.losalary and emp.salary <= salarygrade.hisalary
			emp.salary BETWEEN salarygrade.losalary and salarygrade.hisalary
*/
	SELECT 
		t1.ename ,
		t1.`salary`,
		t2.*
	FROM emp t1, salarygrade t2
	WHERE t1.`salary` BETWEEN t2.`losalary` AND t2.`hisalary`;

4.查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级

/*
	分析:
	    1. 员工姓名,工资 emp , 职务名称,职务描述 job 部门名称,部门位置,dept  工资等级 salarygrade
		2. 条件: emp.job_id = job.id and emp.dept_id = dept.id and emp.salary BETWEEN salarygrade.losalary and salarygrade.hisalary
						
*/
	SELECT 
		t1.`ename`,
		t1.`salary`,
		t2.`jname`,
		t2.`description`,
		t3.`dname`,
		t3.`loc`,
		t4.`grade`
	FROM 
		emp t1,job t2,dept t3,salarygrade t4
	WHERE 
		t1.`job_id` = t2.`id` 
		AND t1.`dept_id` = t3.`id`
		AND t1.`salary` BETWEEN t4.`losalary` AND t4.`hisalary`;

5.查询出部门编号、部门名称、部门位置、部门人数

/*
	分析:
		1.部门编号、部门名称、部门位置 dept 表。 部门人数 emp表
		2.使用分组查询。按照emp.dept_id完成分组,查询count(id)
		3.使用子查询将第2步的查询结果和dept表进行关联查询
					
*/
	SELECT 
		t1.`id`,t1.`dname`,t1.`loc` , t2.total
	FROM 
		dept t1,
		(SELECT
		dept_id,COUNT(id) total
	FROM 
		    emp
	    GROUP BY dept_id) t2
	WHERE t1.`id` = t2.dept_id;

6.查询所有员工的姓名及其直接上级的姓名,没有领导的员工也需要查询

/*
	分析:
		1.姓名 emp, 直接上级的姓名 emp
			* emp表的id 和 mgr 是自关联
		2.条件 emp.id = emp.mgr
		3.查询左表的所有数据,和 交集数据
			* 使用左外连接查询
				
*/
	/*
	select
		t1.ename,
		t1.mgr,
		t2.`id`,
		t2.ename
	from emp t1, emp t2
	where t1.mgr = t2.`id`;
			
	*/
			
	SELECT 
		t1.ename,
		t1.mgr,
		t2.`id`,
		t2.`ename`
	FROM emp t1
	LEFT JOIN emp t2
	ON t1.`mgr` = t2.`id`;

4.视图

1.视图的概念

从SQL的角度来看,视图就是一张表,存在表名、字段列。在SQL语句中,也并不区分实体表和视图。

视图和实体表的区别就在与:是否保存了实际数据。

视图本身是一个不含任何数据的虚拟表,数据库中存放视图的定义(保存好的SELECT语句),而不存放视图对应的数据。

实体表中保存实际数据,使用实体表创建视图后,实体表中的数据发生变化,视图查询出的数据就会发生变化。

从视图中读取数据时,视图会在内部执行对应的SELECT语句,并创建出一张临时表。
视图的优点:将频繁使用的查询语句保存成视图,这样就不用每次都重新写。在创建好视图后,可以将视图和其他实体表一样,在SELECT语句中进行调用。

对于常用的联表查询,可将联表的结果创建为视图,后续使用联表结果时,不用重新写select语句,直接调用视图即可。

注意:修改视图数据后,原表数据也会随之修改

2.视图的用法

1.创建视图:

    create view 视图名 as
	select   列名(可以有多个)
	from  表名
	where 约束条件;

例:

例如:在student_list视图中,显示出学生表(student)中,
年纪大于等于18岁的学生信息。
	create  view  student_list as 
	select *
    from student
    where age>=18;

2.查询视图:

     select * from 视图名
     where 约束条件;

3.删除视图:

 drop view 视图名;

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQL中,(table)和视图(view)是两种不同的数据库对象,但它们之间存在关联和相互作用的关系。 1. 定义:是由行(记录)和列(字段)组成的结构化数据集合,用于存储和组织数据。视图是基于一个或多个的查询结果集,它是一个虚拟,没有实际存储数据,而是根据查询定义动态地生成结果集。 2. 数据存储:中的数据是实际存储在数据库中的,可以通过插入、更新和删除操作修改中的数据。而视图并不存储任何数据,它只是一个查询结果的临时示。 3. 结构定义:具有自己的结构和约束条件,包括列名、数据类型、主键、外键等。视图的结构定义是基于底层的查询语句定义的,它可以选择特定的列、进行筛选、连接操作。 4. 数据操作:对于,可以直接对其进行插入、更新和删除等操作,修改中的数据会直接影响数据库中的实际数据。对于视图,由于它是基于一个或多个查询结果生成的,所以对视图的数据操作可能会受到一些限制,例如某些视图不能进行直接的插入、更新和删除操作。 5. 数据访问:使用SELECT语句可以从视图中检索数据。对于,SELECT语句从实际存储的数据中获取结果;而对于视图,SELECT语句从基础的查询结果中获取结果。 总的来说,视图是对的查询结果进行封装,提供了一种逻辑上的数据展示方式,可以简化复杂的查询操作,并提供了一定程度的数据安全性和保护。则是实际存储和组织数据的对象。视图与底层之间可以进行联结、筛选、排序等操作,通过视图可以方便地访问和操作底层中的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值