数据库中多表查询以及练习

多表查询

1.基本查询语法

	select  列表名称  from  表名列表  where  条件
  • 准备笔记
		-- 部门信息表
		CREATE TABLE dept(
			id INT PRIMARY KEY AUTO_INCREMENT,
			NAME VARCHAR(20),
			);
		-- 员工信息表
		CREATE TABLE emp(
			id INT PRIMARY KEY AUTO_INCREMENT,
			NAME VARCHAR(20),
			sex CHAR(2),
			salary DOUBLE ,
			join_date DATE,
			dept_id INT,
			FOREIGN KEY (dept_id) REFERENCES dept(id)
			);

数据信息:
emp表数据
在这里插入图片描述
dept表数据
在这里插入图片描述

2.笛卡尔积:

	* 有两个集合A,B,取这两个集合的所有组成情况。
		emp表有5条数据,dept表有3条数据,使用笛卡尔积查询会有15条数据,
		存在重复无用的数据
  • 实例表现
    在这里插入图片描述

3.多表查询

  • 1.内连接查询:

       1.隐式内连接:
     		* 语法:使用where条件消除无用数据
     		* 例子
     			-- 查询所有员工信息和对应的部门信息
    
	SELECT * FROM emp,dept  WHERE emp.dept_id = dept.id ;

结果如图(消除了刚才重复的数据)
在这里插入图片描述

	2.显式内连接:
		* 语法:select 字段列表 from 表名1 [inner] join 表名2 on 条件;
		* 关键字:[inner]  join   on  【inner可以省略不写】
		* 例如
			-- 查询所有员工信息和对应的部门信息
    SELECT * FROM emp INNER JOIN dept ON emp.dept_id = dept.id;
	SELECT * FROM emp JOIN dept ON emp.dept_id = dept.id;

结果如上图(只是换了一种方法)

	注意事项:
				1.从哪些表查询数据
				2.查询的条件是什么
				3.查询哪些字段
  • 2.外连接查询:

     例子:先在emp表添加小白龙数据,但是不添加部门信息
    

在这里插入图片描述

-- 查询所有员工信息,如果员工有部门,则查询部门名称,如果没部门,则不显示部门名称
	SELECT
		t1.*,t2.name
	FROM
		emp t1,dept t2
	WHERE
		t1.dept_id = t2.id;

结果如图:没有小白龙数据
在这里插入图片描述

注意:使用左外连接或右外连接可以解决

	1.左外连接
		* 语法: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;

结果如图:小白龙出现
在这里插入图片描述

	2.右外连接
		* 语法:select 字段列表 from 表名1 right [outer] join 表名2 on 条件;
		* 查询的是右表所有数据以及与右表交集部分(条件)
	SELECT
		t1.*,t2.name	
	FROM 
		emp t1 RIGHT JOIN dept t2
	ON 
		t1.dept_id = t2.id;
  • 3.子查询:

     	* 概念:查询中嵌套查询,称嵌套查询是子查询。
    
    • 子查询不同情况

        	1.子查询的情况是单行单列的
        		* 子查询可以作为条件,使用运算符去判断的  
      

– 查询员工工资小于平均工资的人

		-- 1.查询最高工资是多少 9000
		SELECT MAX(salary) FROM emp;
		-- 2.查询员工信息,并且工资等于9000
		SELECT * FROM emp WHERE salary = 9000;		
		-- 一条sql语句完成操作(合并上面两条语句)
		SELECT * FROM emp WHERE emp.salary = (SELECT MAX(salary) FROM emp);

结果如图:
在这里插入图片描述

		2.子查询的情况是多行单列的
			* 子查询可以作为条件,使用运算符in 作为条件

– 查询财务部和市场部的员工信息

		-- 1.普通查询财务部和市场部的员工信息
		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 (3,2);
		-- 子查询
		SELECT
			* 
		FROM 
			emp 
		WHERE 
			dept_id IN (SELECT id 
						FROM dept 
						WHERE NAME= '财务部' OR NAME= '市场部'
						); 

结果如图:
在这里插入图片描述

		3.子查询的情况是多行多列的
			* 子查询可以作为一张虚拟表

– 查询员工入职日期是2013-5-10日之后的员工信息和部门信息

	分析:
		1.先查询入职日期是2013-5-10日之后的员工信息
		SELECT * FROM emp WHERE join_date > '2013-05-10';

结果如图:
在这里插入图片描述

		2.再将结果作为一张虚拟表		
		SELECT 
			* 
		FROM 
			dept t1 ,(SELECT * FROM emp WHERE join_date > '2013-05-10') t2 
		WHERE
			t1.id = t2.dept_id;

结果如图:
在这里插入图片描述

4.多表查询实例练习

  • 准备工作
    创建以下表(以下所有的代码使用了 别名
 	-- 部门表
	CREATE TABLE dept (
	  id INT NOT NULL,
	  dname VARCHAR(50) DEFAULT NULL,
	  loc VARCHAR(50) DEFAULT NULL,
	  PRIMARY KEY (id)
	  )
	-- 员工表
	CREATE TABLE emp (
		id INT PRIMARY KEY,  -- 员工id
		ename VARCHAR(20),  -- 员工姓名
		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)
	);
	-- 职务表
	CREATE TABLE `job` (
	  `id` INT NOT NULL,
	  `jname` VARCHAR(20) DEFAULT NULL,
	  `description` VARCHAR(50) DEFAULT NULL,
	  PRIMARY KEY (`id`)
	)
	-- 工资等级表
	CREATE TABLE salarygrade(
		grade INT PRIMARY KEY,
		losalary INT,
		hisalary INT
	);
  • 练习1

     1.查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述
     	分析:
     		1.查询员工编号,员工姓名,工资 emp表 , 职务名称,职务描述 job表
     		2.查询条件:t1.job_id = t2.id
    
		SELECT
			t1.id,          -- 员工编号
			t1.ename,       -- 员工姓名
			t1.salary,		-- 工资
			t2.jname,		-- 职务名称
			t2.description	-- 职务描述
		FROM  
			emp t1 , job t2
		WHERE
			t1.job_id = t2.id
  • 练习2

      2.查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置
     	分析:
     		1.员工编号,员工姓名,工资  emp表   职务名称,职务描述  job表  
     		  部门名称,部门位置  dept表
     		2.查询条件 t1.job_id = t2.id and t1.dept_id = t3.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

      3.查询员工姓名,工资,工资等级。
     	分析:
     		1.员工姓名,工资,emp表   工资等级  salarygrade表
     		2.查询条件:emp.salary>=losalary and emp.salary<=hisalary
     					或emp.salary between losalary and hisalary
    
		SELECT
			t1.ename,   -- 员工姓名
			t1.salary,  -- 员工工资
			t2.grade    -- 工资等级
		FROM
			emp t1,salarygrade t2
		WHERE
			t1.salary BETWEEN t2.losalary AND t2.hisalary;
  • 练习4

      4.查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
     	分析:
     		1.员工姓名,工资 emp表 , 职务名称,职务描述,job表 ,
     		  部门名称,部门位置 dept表 ,工资等级 salarygrade表
     		2.查询条件:
    
		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

     5.查询部门编号,部门名称,部门位置,部门人数
     	分析:
     		1.部门编号,部门名称,部门位置 dept 表  部门人数  emp表
     		2.使用分组查询,把dept_id分组,count(id),形成虚拟表
     		3.使用子查询,虚拟表
    
		-- 虚拟表
		SELECT 
			dept_id,COUNT(id)
		FROM
			emp
		GROUP BY dept_id;
		SELECT
			t1.id,t1.dname,t1.loc,t2.tatol
		FROM
			dept t1,(SELECT dept_id,COUNT(id) tatol
				 	FROM  emp
				 	GROUP BY dept_id) t2
		WHERE t1.id = t2.dept_id;
  • 练习6(难理解)

     6.查询所有员工的姓名及其直接上级名称,没有领导的员工也需要查询
     	分析:
     		1.姓名  emp表  ,直接上级名称  emp表
     				注意 * emp表的id和mgr是自关联的
     		2.条件 emp.id等于emp.mgr
     		3.查询右表的所有数据和交集数据,使用左外连接
    
		SELECT 
			t1.ename,	-- 员工姓名
			t1.id,		-- 员工id
			t2.ename	-- 员工的上级领导姓名
		FROM emp t1
		LEFT JOIN emp t2
		ON t1.mgr = t2.id ;

图形理解
在这里插入图片描述

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值