首页 > 数据库 >mysql多表查询

mysql多表查询

时间:2023-04-13 17:34:13浏览次数:43  
标签:多表 sal -- 查询 emp mysql deptno SELECT

查询加强


查询到的表的结构

-- 查询加强

-- 使用where语句

-- 1.如果查找1991.1.1后入职的员工
-- 注意:mysql,日期类型可以直接比较,需要注意和表中的格式一致
SELECT * FROM  emp
WHERE hiredate>'1991.1.1';

-- 2.使用like操作符(模糊)
-- %:表示0到多个任意字符  _:表示单个任意字符
-- 2.如何显示首字母为S的员工的姓名和工资
SELECT ename,sal FROM emp
WHERE ename LIKE 'S%';

-- 3.如果显示第三个字符为大写o的所有员工的姓名和工资
SELECT ename,sal FROM emp
WHERE ename LIKE '__O%';

-- 4.如果显示没有上级的员工的情况(mgr记录了雇员上级的编号)

SELECT *FROM emp
WHERE mgr IS NULL;

-- 5.查询表的结构
DESC emp;

-- 使用order by 子句
-- 1.如何按照工资从低到高的顺序【升序】,显示雇员信息
SELECT * FROM emp 
ORDER BY sal ASC;-- 默认的,asc写不写都可以
-- 2.按照部门号升序而雇员的工资降序排列,显示雇员信息(排序之后再排序)
-- (这个排序分顺序,前面的前排)意思是先按照部门号进行升序,然后按照相同部门号的内部的薪水进行降序(分组来看)


SELECT * FROM emp
ORDER BY deptno ASC,sal DESC ;


  • 排序第二题的结果

分页查询

在实际开发中的查询中,如果一个表有10w条记录,我们查询这个表,不可能将10w张记录同时返回,这就设计到分页操作

-- 分页查询
-- 按照雇员的工号升序取出,每页显示3条记录,分别显示第一页,第二页,第三页
-- limit start,rows 表示每次从start+1行开始取,每次取出rows行 

-- 第一页
SELECT * FROM emp
 ORDER BY empno
 LIMIT 0,3;-- 1~3
 
 -- 第二页
 SELECT * FROM emp
 ORDER BY empno
 LIMIT 3,3;-- 4~6
 
 -- 第三页
SELECT * FROM emp
ORDER BY empno 
LIMIT 6,3; -- 7~9
 
 

练习题

-- 练习
 -- 按照雇员的工号降序取出,每页显示5条记录,请分别显示第三页 第五页对应的sql语句
 
 -- 第三页
SELECT * FROM emp
ORDER BY empno DESC
LIMIT 10,5; 
 -- 第五页
 SELECT * FROM emp
 ORDER BY empno DESC
 LIMIT 20,5;
 
 
 
 

分组加强(听起来很迷糊省略)


多子句查询


注意各个子句的顺序

多表查询

多表笛卡尔集


从上面的评论内容可以看成,这个评论的内容一定是来自一个评论表和一个商品表



多表查询的关键在于对笛卡尔集进行过滤操作,而上面2个表都有部门号这个列,必须部门号相同才是有效的记录,所有可以通过部门号相同来进行过滤


注意上面的建议:多表查询的条件不能少于表的个数-1。2张表的过滤条件至少1个,3张表查询过滤条件至少2个,依次类推

多表查询

-- 1.如果显示部门号为10的部门名,员工名和工资(部门号也一起显示)

/*
	员工名 工资 emp表
	部门名 部门号 dept表
*/

-- 过滤条件为工资必须在相应的级别内
SELECT ename,sal,dname,emp.`deptno` FROM emp,dept
WHERE emp.`deptno`= dept.`deptno` AND emp.`deptno`=10;

-- 2.显示各个员工的姓名,工资,及其工资的级别
-- 姓名和工资-->emp表
-- 工资级别--->salgrade表
SELECT ename,sal,grade FROM emp,salgrade 
WHERE sal BETWEEN losal AND hisal;



写一个sql先写一个简单的,然后进行条件的叠加

  • 练习

-- 练习
-- 显示雇员名,雇员工资以及所在部门的名字,并按照部门排序[降序排]

-- 雇员名,雇员工资 emp表
-- 部门名 dept表

SELECT  ename,sal,dname , emp.`deptno` FROM emp,dept

WHERE emp.`deptno` = dept.`deptno` ORDER BY emp.`deptno` DESC;




order 放在 where后面

自连结


alias:别名

  • 当我们使用同一个表名时将会报错

    1.起的别名不需要使用引号引起来2.别名的as可以省略
-- 多表查询的自连接
-- 显示公司员工名字和他的上级名字

SELECT worker.`ename` AS '职员名',boss.`ename` AS   '上级名'
 FROM   emp   worker ,  emp  boss
 WHERE worker.`mgr`= boss.`empno`;
 
SELECT * FROM emp;
 

将1张表当成2张表使用,过滤条件是雇员的上级编号=上级的员工号
查询结果

  • 总结

    必须对分成的2张表分别取别名,否则将会报错

多行子查询


单行子查询

--  子查询演示
-- :如何显示与SMITH同一部门的所有员工
# 分析:我们在查询时限制条件,肯定是部门号等于SMTH的部门号
-- 1.可以先查询到SMITH的部门号
-- 2.把上面的select语句当作一个子查询来使用


-- 1.查询到SMITH的部门号
SELECT deptno 
FROM emp WHERE ename = 'SMITH';

-- 2.将上面的SQL进行嵌套


## 因为该子查询返回的只有一行,所有也称为单行子查询
SELECT ename,deptno 
FROM emp WHERE deptno=(SELECT deptno 
FROM emp WHERE ename = 'SMITH');

  • 子句返回结果
  • 嵌套后返回的结果

    在mysql中等于用=表示,不等使用!=或者<>表示

多行子查询

-- 多行子查询

-- 如何查询和部门10的工作相同的雇员的
-- 名字 岗位 工资 部门号 但是不含10号部门自己的雇员
-- 思路:
-- 1.先查询到部门=10有哪些工作(需要注意对返回的工作进行去重)
SELECT DISTINCT job FROM emp
WHERE deptno =10;
-- 2.将上面查询的结果当作子查询使用
SELECT job,sal,deptno FROM emp
WHERE job IN(SELECT DISTINCT job FROM emp
WHERE deptno =10);-- job必须是部门号=10中的一个

-- 进一步优化,不能包含10号部门自己的员工

SELECT job,sal,deptno FROM emp
WHERE job IN(SELECT DISTINCT job FROM emp
WHERE deptno =10)AND deptno !=10;

子查询临时表

子句运行结果:先找到各个类别,价格最高的商品 ,并将其作为一个临时表

然后将临时表和esc_goods表进行多表查询并过滤即可得到结果

经过分析:2个表的过滤条件应该是临时表是最高价格=商品表的价格 并且要求cat_id相同

  • 完整代码
-- 查询ecshop中各个类别中,价格最高的商品

-- 1.查询商品表
-- 先得到各个类别中,价格最高的商品 max+grop by cat_id,当做临时表
 SELECT cat_id,MAX(shop_price) 
	FROM ecs_goods
	GROUP BY cat_id;
	
	
	
# 2.将前面的表作为临时表

SELECT goods_id,ecs_goods.cat_id,goods_name,shop_price
FROM (

	SELECT cat_id,MAX(shop_price) AS max_price-- 将该列起别名
	FROM ecs_goods
	GROUP BY cat_id)temp,-- 将临时表起个别名temp
	ecs_goods
	WHERE temp.cat_id = esc_goods.cat_id
	AND  temp.max_price = esc_goods.shop_price;
	
  • 最终运行结果

all 和any

子句:显示部门号=30的所有薪资

SELECT * FROM emp;

**all需要和其中的所有对比**

-- all和any的使用


-- 要求:显示工资比部门30的所有员工的工资高的员工的姓名 工资和部门号

# 子查询

SELECT sal FROM emp
WHERE deptno=30;

-- 子查询将会返回多个结果,直接>将会出错,用all指向所有
-- 方案一
SELECT ename,sal,deptno FROM emp

WHERE sal>ALL(SELECT sal FROM emp
WHERE deptno=30
);

-- 方案二(在子句中直接查询最高工资)
SELECT ename,sal,deptno FROM emp
WHERE sal>(SELECT MAX(sal)FROM emp WHERE deptno =30);

any只用和其中的一个对比

-- 演示any的使用

-- 要求:显示工资比部门30其中的一个员工的工资高的员工的姓名 工资和部门
-- 方案一
SELECT ename,sal,deptno FROM emp

WHERE sal>ANY(SELECT sal FROM emp
WHERE deptno=30
);
-- 方案二(比其中的一个高,一定是比其中的最低工资高)
SELECT ename,sal,deptno FROM emp

WHERE sal>(SELECT MIN(sal) FROM emp
WHERE deptno=30
);

多列子查询

多行子查询的意思是子查询的结果返回的是多列的数据

  -- 多列子查询
  -- 思考如何查询与ALLEN的部门和岗位完全相同的所有雇员(并且不含
  -- ALLEN本人)
  -- 对于该种情况的格式(和子查询字段一一对应)
  -- (字段1,字段2...)=(select 字段1,字段2...)
  -- 子查询:找到ALLEN的部门和岗位
  
   SELECT job,deptno FROM emp
   WHERE ename='SMITH'
   
   
   SELECT * FROM emp
   
   WHERE(job,deptno)=( SELECT job,deptno FROM emp
   WHERE ename='ALLEN')AND ename!='ALLEN';

练习

  • 数据来源
-- 查询和宋江数学 英语 语文成绩完全相同的学生

-- 子查询:查询出宋江的数学 英语 语文成绩

SELECT math,chinese,english FROM student
WHERE `name`='宋江';

-- 复合句
SELECT * FROM student
WHERE (math,chinese,english)=(SELECT math,chinese,english FROM student
WHERE `name`='宋江');

子查询练习

# 在from 中使用子查询
-- 查找每个部门工资高于本部门平均工资的人的资料
-- 提示将子查询当成一个临时表使用(很自然的想到)
-- 子查询
-- 1.找到每个部门的平均工资

SELECT deptno,AVG(sal)AS avg_sal FROM emp
GROUP BY deptno;
-- 2.将上面的子查询作为一个临时表和emp双表笛卡尔积

SELECT ename,job,mgr,hiredate,sal,comm,emp.`deptno`

FROM emp,(SELECT deptno,AVG(sal)AS avg_sal FROM emp
GROUP BY deptno)AS temp
WHERE emp.`deptno`=temp.`deptno`AND sal>temp.avg_sal;

-- 查找每个部门工资最高的人的详细资料

-- 1.先找到每个部门工资最高的人

SELECT MAX(sal)AS max_sal,deptno FROM emp

GROUP BY deptno;


-- 2.进行多表查询

SELECT ename,job,hiredate,sal,comm,emp.`deptno`
FROM emp,(SELECT MAX(sal)AS max_sal,deptno FROM emp

GROUP BY deptno)AS temp

WHERE emp.`deptno`=temp.`deptno`AND sal=max_sal

-- 查询每个部门的信息(包含:部门名 部门编号 地址)
-- 和人员数量
-- 1.部门名 部门编号 地址来自dept表
-- 2.每个部门的人员数量-->构造一个临时表
-- 1.临时表sql
SELECT COUNT(*)AS '部门人员数量',deptno FROM emp
GROUP BY deptno
-- 2.嵌套操作
SELECT dname,dept.deptno,loc,部门人员数量 FROM dept,
(SELECT COUNT(*)AS '部门人员数量',deptno FROM emp
GROUP BY deptno)AS temp
WHERE dept.`deptno`=temp.`deptno`;



  • 运行结果

    另一种写法(简易显示列)
-- 另一种写法( 可以将一张表中的所有的列都显示出来)
-- 表.*表示将该表所有的列都显示出来
SELECT temp.*,loc,dname FROM dept,
(SELECT COUNT(*)AS '部门人员数量',deptno FROM emp
GROUP BY deptno)AS temp
WHERE dept.`deptno`=temp.`deptno`;

** 如果2个表时只写一个*,就是将2张表的列都显示出来了**

当2张表的列名不重复的时候,才可以直接写列名

表复制和去重


desc+表名 查看表的结构

-- 表的复制
-- 为了对某条sql语句进行效率测试,我们需要海量的数据时,可以使用此法为表
-- 创建海量的数据
-- 1.创建一张表
CREATE TABLE my_tab02
(
id INT ,
`name` VARCHAR(32),
sal DOUBLE ,
job VARCHAR(32),
deptno INT);

-- 2.将emp表的记录复制到my_tab02
-- 将emp表对应的列的信息复制的my_tab02表的对应字段
INSERT INTO my_tab02 -- 所需要的列要匹配
(id,`name`,sal,job,deptno)
SELECT empno,ename,sal,job,deptno FROM emp;
-- 3.进行自我复制
-- 反复执行该语句,数据将会成倍增加
INSERT INTO my_tab02-- 此时
SELECT * FROM my_tab02




删除一张表的重复记录

-- 如何删除一张表重复的记录
-- 1.先创建一张表my_tab03
CREATE TABLE my_tab03 LIKE emp;-- 将emp表的结构(列信息)复制给my_tab03

-- 2.使用自我复制使得该表有重复记录

-- 将下面的复制语句执行2遍就已经有了13条重复的记录(总共26条记录)
INSERT INTO my_tab03
SELECT * FROM emp;

-- 3.考虑去重my_tab03的记录

-- 思路:
/*
1.先创建一张临时表my_temp,该表的结构和my_tab03一样
2.把my_tab03的记录通过disdtinct处理后复制到my_temp中
3。清除掉my_tab03的记录
4.把my_temp的记录复制到my_tab03中
5.drop掉临时表my_temp
*/

-- 1.先创建一张临时表my_temp,该表的结构和my_tab03一样
CREATE TABLE my_temp LIKE my_tab03
-- 2.把my_tab03的记录通过disdtinct处理后复制到my_temp中

INSERT my_temp 
SELECT DISTINCT * FROM my_tab03

-- 此时my_temp包含13条不重复的记录
-- 3.清除掉my_tab03的记录
DELETE FROM my_tab03

-- 4.把my_temp的记录复制到my_tab03中
INSERT my_tab03 
SELECT * FROM my_temp;
-- 5.删除掉临时表my_temp

DROP my_temp;


有点想java中交换2个变量的值,使用一个中间变量进行过度

其实当将my_tab03表中的数据数据复制到的temp时,可以直接原表删除,然后将临时表该名为我们之间的表即可

合并查询

  • 语句一结果
  • 语句二结果

    使用union all合并

    只能进行简单的合并,并不能去重,而且只有当2个子句查询的列是一样的才能进行合并
    union合并

    可以将相同的记录去除

外连接需求

  • 多表查询思路


思路概括为多表笛卡尔积,然后使用使用where子句进行过滤
是根据关联条件,显示所有匹配的记录,如果匹配不上将不会显示

使用前面的多表查询实现

  • dept表
  • emp表

    使用多表查询的结果

这样的方式不能显示没有员工的部门SALES,emp表没有和dept关联的deptno

由此可以引出我们的外连接来解决这个问题


左外连接:左边这个表即使没有匹配的记录也会将左边这个表的记录显示出来
右外连接:右边这个表即使没有匹配的记录也会将右边这个表的记录显示出来

左外连右外连

exam和stu表

-- 左外连右外连

-- 1.创建stu
CREATE TABLE stu (
	id INT,
	`name` VARCHAR(32));
INSERT INTO stu VALUES(1,'jack'),(2,'tom'),(3,'kity'),(4,'nono');

-- 2.创建exam

CREATE TABLE exam(
	id INT ,
	grade INT);

INSERT INTO exam VALUES (1,56),(2,76),(11,8);
SELECT * FROM stu;


-- 要求:显示所有人的成绩,姓名和id号,如果没有成绩也要显示该人的
-- 姓名和id,成绩显示为空
-- 1.直接使用双表笛卡尔积,然后按照id号相同过滤

SELECT `name`,stu.`id`,grade 
FROM stu,exam
WHERE stu.`id`=exam.`id`

-- 此时发现没有成绩的学生将没有显示
-- 2.改成左外连接(where去除,表之间的,不要)
-- 此时左边的表就是左表,右边就是右表
SELECT `name`,stu.`id`,grade 
FROM stu LEFT JOIN exam ON
 stu.`id`=exam.`id`

-- 此时左表即使没有匹配上也将会显示出来

-- 使用右外连接(显示所有成绩,即使没有名字匹配,显示空)

SELECT `name`,stu.`id`,grade 
FROM stu RIGHT JOIN exam ON
 stu.`id`=exam.`id`





练习

-- 列出部门名称和这些部门的员工信息(名字和工作),同时列出
-- 那些没有员工的部门名
-- 1.使用右外连接实现
SELECT dname,ename,job
FROM emp RIGHT JOIN dept
 ON dept.`deptno`=emp.`deptno`
 -- 2.使用左外连接实现-
 -- 将2个表交换一下位置就可以了
 SELECT dname,ename,job
FROM dept LEFT JOIN emp
 ON dept.`deptno`=emp.`deptno`
 

 
 

标签:多表,sal,--,查询,emp,mysql,deptno,SELECT
From: https://www.cnblogs.com/swtaa/p/17292875.html

相关文章

  • Kibana查询语法使用手册【转】
    阅读目录全文搜索按字段搜索通配符搜索匹配单一字符匹配任意多个字符范围搜索布尔搜索分组搜索转义特殊字符速查全文搜索在搜索栏输入login,会返回所有字段值中包含login的文档使用双引号包起来作为一个短语搜索"likeGecko" 也可以按页面左侧显示的字段搜索限定......
  • Mybatis_06 _查询语句对应关系
    Mybatis_06对应关系多对一:使用关联association一对多:使用集合collection创建SQL表:CREATETABLE`teacher`(`id`INT(10)NOTNULL,`name`VARCHAR(30)DEFAULTNULL,PRIMARYKEY(`id`))ENGINE=INNODBDEFAULTCHARSET=utf8CREATETABLE`student`(`id`INT(10......
  • MySQL面试题-2023
                          参考链接:https://blog.csdn.net/weixin_41622043/article/details/103426652https://xiaolincoding.com/mysql/base/how_select.html ......
  • mysql创建百万条虚假数据进行学习
    1.创建基础表CREATETABLE`app_user`(`id`bigint(20)unsignedNOTNULLAUTO_INCREMENT,`name`varchar(50)DEFAULT''COMMENT'用户昵称',`email`varchar(50)NOTNULLCOMMENT'用户邮箱',`phone`varchar(20)DEFAULT'......
  • mysql,dorics数据库查询不同类型数据前10条信息
    selectt1.id,t1.namefrom(selectt.id,t.name,row_number()over(partitionbyt.idorderbyt.date)rnfromAt)t1wheret1.rn<=10;结果如下:  ......
  • oracle递归查询法
    select*from表名startwith查询的条件connectbyprior等值条件(一个表中两个值相等的字段)查询的结果集:满足连接的值=查询条件,startwith子句:遍历起始条件,有个小技巧,如果要查父结点,这里可以用子结点的列,反之亦然。connectby子句:连接条件。......
  • 在LINQPad中使用FreeSql查询数据库
    如何在LINQPad中使用FreeSqlLINQPad是一款强大的C#交互式编程环境,它可以让你轻松地编写和测试C#代码片段。除了作为一个交互式编程环境,LINQPad还可以用来连接各种数据源,包括SQL数据库、NoSQL数据库、Web服务等等。此外,LINQPad还支持使用NuGet包管理器来安装和管理第三方库。有时......
  • Docker MySql8 创建、删除、授权用户
    1、登录MySql8#登录数据库dockerexec-itmysql8mysql-uroot-proot123456#切换数据库实例usemysql;2、用户操作2.1、查看用户selecthost,user,authentication_string,pluginfromuser;2.2、创建本地用户#创建一个用户名为admin,密码为admin123456的......
  • Linux安装MySQL
    1、下载MySQLMySQL官网:https://downloads.mysql.com/archives/community/。下载Linux版本的MySQL安装包,这里我选择的是64位、8.0.31版本,下载的压缩包名称:mysql-8.0.31-linux-glibc2.12-x86_64.tar.xz。  2、Linux安装MySQL1、将下载的压缩包,上传到Linux的指定目录并解压......
  • MySQL的锁机制
    锁概述锁是计算机协调多个进程或线程并发访问某一资源的机制。并发控制技术在数据库中,数据可以允许多个用户同时访问,因此在并发场景下需要确保数据的一致性,并发场景有三种:读-读:多用户并发读不会有问题读-写:可能出现脏读、幻读、不可重复读写-写:并发更新同一行会导致丢失更......