• MySQL入门指南4(查询进阶,外连接)


    前期回顾:

            MySQL入门指南1(进入命令行,数据库,数据表操作)

            MySQL入门指南2(SQLyog使用,增删改查)

            MySQL入门指南3(常用函数)

     

    目录

    一、查询进阶

            1.查询增强

            2.多表查询

            3.子查询

            4.合并查询

            5.表的复制

    二、外连接

            1.左外连接

            2.右外连接

    三、最后的话


     

    一、查询进阶

            1.查询增强

    前面我们介绍了mysql表的基本查询,这里我们将会在基本查询的基础上进行一些扩展。

    代码演示如下:

    1. -- 查找1992.1.1 后入职的员工
    2. -- 这里的hiredate时日期类型,日期类型可以直接比较,但要注意格式
    3. SELECT * FROM emp
    4. WHERE hiredate >'1992-01-01';
    5. -- 查找首字母为S的员工的姓名与工资
    6. -- 在近似查询中 % 代表0到多个字符
    7. SELECT ename,sal FROM emp
    8. WHERE ename LIKE 'S%';
    9. -- 查找第三个字符为大写O的员工的姓名与工资
    10. -- 在近似查询中 _ 表示一个字符
    11. SELECT ename,sal FROM emp
    12. WHERE ename LIKE '__O%'; -- 此处有两个 _
    13. -- 显示没有上级雇员的情况
    14. -- 没有上级即:该记录的mgr为NULL
    15. SELECT * FROM emp
    16. WHERE mgr IS NULL; -- 不可用 = NULL
    17. -- 查询表结构
    18. DESC emp;
    19. -- 按照工资从低到高排序
    20. SELECT * FROM emp
    21. ORDER BY sal;-- 默认升序 ASC
    22. -- 按照部门升序,工资降序排序
    23. -- 多重排序,按照要求一次排序
    24. SELECT * FROM emp
    25. ORDER BY deptno ASC ,sal DESC ;
    26. -- 显示每种岗位的雇员总数,平均工资
    27. SELECT COUNT(*),FORMAT(AVG(sal),2),job
    28. FROM emp
    29. GROUP BY job;
    30. -- 显示雇员总数,以及获得补助的雇员数
    31. -- 未获得补助的员工 comm 值为NULL
    32. -- 在使用 COUNT(列) 时正好不计算在内
    33. SELECT COUNT(*),COUNT(comm)
    34. FROM emp;
    35. -- 统计没有获得补助的雇员数
    36. -- 若为真,则1 ,进而count统计时会统计上
    37. SELECT COUNT(IF(comm IS NULL,1,NULL)) FROM emp;
    38. SELECT COUNT(*)-COUNT(comm) FROM emp;
    39. -- 显示管理员的总人数
    40. SELECT COUNT(job) FROM emp
    41. WHERE job='MANAGER';
    42. -- 统计各部门平均工资,且大于1000,
    43. -- 并降序排列 前两条记录
    44. SELECT FORMAT(AVG(sal),2) AS avg_sal ,deptno
    45. FROM emp -- 从emp表中查询
    46. GROUP BY deptno -- 按照部门分组
    47. ORDER BY avg_sal DESC -- 降序排列
    48. LIMIT 0,2; -- 分页查询前两条记录
    49. -- 总结:如果select语句同时包含 group by,
    50. -- having,limit,order by, 一般按照以下顺序
    51. SELECT column1,column2 FROM `table`
    52. GROUP BY `column`
    53. HAVING `condition`
    54. ORDER BY `column`
    55. LIMIT `start`,`rows`;
    除此之外,我们再介绍一下分页查询当我们的数据记录非常多时,我们可能需要分页查询。

     分页查询基本语法:

            SELECT  .....FROM ......

                     LIMIT  start ,rows;

    代码演示如下: 

    1. -- 按照雇员id排序 每页显示三条记录
    2. SELECT * FROM emp
    3. ORDER BY empno
    4. LIMIT 0,3; -- 从第0+1行开始,得到三条记录
    5. -- 按照雇员id排序 每行显示5条记录
    6. SELECT * FROM emp
    7. ORDER BY empno
    8. LIMIT 3,5; -- 从第3+1行开始,得到五条记录

            2.多表查询

            多表查询是基于两个或者两个以上的表的查询,在实际应用中,查询单个表可能不能满足你的需求,因此这里我们就引出了多表查询。

            当我们同时查询多个表时,不同的表之间会形成笛卡尔集。我们需要在笛卡尔集的基础上加上筛选条件来满足我们的要求。

    490ca0d09f00406fba503126b9392c62.png

    两表之间形成笛卡尔集

     代码演示如下:

    1. -- 多表查询
    2. -- 笛卡尔集
    3. -- 显示雇员名,雇员工资及所在部门的名字
    4. SELECT ename,sal,dname
    5. FROM emp,dept
    6. WHERE emp.deptno=dept.deptno; -- 当满足此条件时,才是我们要的结果
    7. -- 提示:多表查询的条件不能少于表数-1 否则会出现笛卡尔集
    8. -- 显示部门号为10的部门名,员工名,工资
    9. SELECT dname,ename,sal
    10. FROM emp,dept
    11. WHERE emp.deptno=dept.deptno&&emp.deptno=10;
    12. -- 显示各个员工的姓名,工资,以及工资级别
    13. SELECT ename,sal,grade
    14. FROM emp,salgrade
    15. WHERE sal BETWEEN salgrade.losal AND salgrade.hisal;
    16. -- 自连接:在同一张表的连接查询
    17. -- 显示公司员工和他的上级的名字
    18. SELECT emp1.ename AS worker ,emp.ename AS `super`
    19. FROM emp AS emp1,emp -- 由于列名不准确,我们要用AS指定列
    20. WHERE emp1.mgr = emp.empno;

            3.子查询

            子查询是指嵌入在其他SQL语句中的SELECT语句,也叫嵌套查询。按查询结果分为单行子查询,多行子查询,多列子查询。

    ​多行子查询代码演示:

    1. -- 多行子查询
    2. -- 1.0如何显示与SMITH同一个部门的所有员工
    3. -- 1.1 先找到SMITH所在部门
    4. SELECT deptno FROM emp
    5. WHERE ename ='SMITH';
    6. -- 1.2 再找那个部门的员工
    7. SELECT * FROM emp
    8. WHERE deptno = (
    9. SELECT deptno FROM emp
    10. WHERE ename ='SMITH')
    11. -- 2.0查询和部门10的工作相同的雇员的信息,
    12. -- 但不包括部门10自己的雇员
    13. -- 2.1 先找部门10有哪些工作
    14. SELECT DISTINCT job FROM emp -- 由于可能多个员工的从事同一个工作,因此要去重。
    15. WHERE deptno = 10;
    16. -- 2.2 再找从事这些工作的所有雇员
    17. SELECT * FROM emp
    18. WHERE job IN( -- 因为部门10可能不止一种工作
    19. SELECT DISTINCT job FROM emp
    20. WHERE deptno = 10);
    21. -- 2.3 在筛选掉部门号为10的雇员
    22. SELECT * FROM emp
    23. WHERE job IN(
    24. SELECT DISTINCT job FROM emp
    25. WHERE deptno = 10)AND deptno!=10;

    子查询当作临时表使用代码演示:

    1. -- 子查询当作临时表使用
    2. -- 显示工资比部门30的所有员工的工资高的员工的姓名、工资、部门号
    3. -- 用MAX
    4. SELECT * FROM emp
    5. WHERE sal>(SELECT MAX(sal) FROM emp WHERE deptno = 30);
    6. -- ALL
    7. SELECT * FROM emp
    8. WHERE sal>ALL(SELECT sal FROM emp WHERE deptno = 30);
    9. -- 显示至少比部门30其中一个高的员工
    10. -- ANY
    11. SELECT * FROM emp
    12. WHERE sal>ANY(SELECT sal FROM emp WHERE deptno = 30);
    13. -- 用MIN
    14. SELECT * FROM emp
    15. WHERE sal>(SELECT MIN(sal) FROM emp WHERE deptno = 30);
    16. -- 将子查询当作临时表使用
    17. SELECT cat_id,MAX(shop_price)
    18. FROM ecs_goods
    19. GROUP BY cat_id;
    20. SELECT goods_id,ecs_goods.cat_id,goods_name,shop_price
    21. FROM ( -- 将子查询结果看成一个临时表再进行相关操作
    22. SELECT cat_id,MAX(shop_price) AS max_price
    23. FROM ecs_goods
    24. GROUP BY cat_id
    25. )temp,ecs_goods
    26. WHERE temp.cat_id = ecs_goods.cat_id
    27. AND temp.max_price=ecs_goods.shop_price;

    多列子查询代码演示:

    1. -- 多列子查询
    2. -- 查询与ALLEN同部门,同工作的人,不包括其本人
    3. -- 1.1先找到ALLEN的部门和工作
    4. SELECT deptno,job FROM emp
    5. WHERE ename ='ALLEN';
    6. -- 1.2
    7. SELECT * FROM emp
    8. WHERE(deptno,job) =(
    9. SELECT deptno,job
    10. FROM emp
    11. WHERE ename ='ALLEN'
    12. )AND ename!='ALLEN';
    13. -- 查询与阳阳同学成绩完全一样的同学
    14. SELECT * FROM student
    15. WHERE(chinese,math,english)=(
    16. SELECT chinese,math,english
    17. FROM student
    18. WHERE `name`='阳阳同学'
    19. )AND `name`!='阳阳同学';
    20. -- from子句中使用子查询
    21. -- 查找部门工资高于本部门平均工资的雇员资料
    22. -- 各部门平均工资
    23. SELECT AVG(sal),deptno
    24. FROM emp
    25. GROUP BY deptno;
    26. SELECT ename,sal,avg_sal,emp.deptno
    27. FROM emp,(
    28. SELECT FORMAT(AVG(sal),2) AS avg_sal,deptno
    29. FROM emp
    30. GROUP BY deptno
    31. )temp
    32. WHERE emp.deptno=temp.deptno
    33. AND emp.sal>avg_sal;
    34. -- 查找每个部门工资最高的人的资料
    35. -- 各部门最高工资
    36. SELECT MAX(sal) AS max_sal,deptno
    37. FROM emp
    38. GROUP BY deptno;
    39. SELECT ename,sal,max_sal,emp.deptno
    40. FROM emp,(
    41. SELECT MAX(sal) AS max_sal,deptno
    42. FROM emp
    43. GROUP BY deptno
    44. )temp
    45. WHERE emp.deptno=temp.deptno
    46. AND emp.sal=temp.max_sal
    47. ORDER BY sal;

     4.合并查询

            有时再实际应用中,为了合并多个 SELECT 语句的结果,可以使用集合操作符号UNION,  UNION  ALL.  它们都是用于取得两个结果集的并集。

            但 UNION   ALL 不会对结果去重,UNION 会自动对结果去重。

     代码演示如下:

    1. -- 合并查询
    2. CREATE TABLE test3(
    3. id INT,
    4. `name` VARCHAR(23),
    5. age INT);
    6. INSERT INTO test3
    7. VALUES(1,'阳阳',19),(2,'小赵',19),(3,'山鱼',20),(4,'浩浩',19);
    8. CREATE TABLE test4(
    9. id INT,
    10. `name` VARCHAR(23),
    11. age INT);
    12. INSERT INTO test4
    13. VALUES(1,'杨枝',19),(2,'小驴',19),(3,'小乐',20),(4,'浩浩',19);
    14. SELECT * FROM test3
    15. UNION ALL -- 直接合并不去重
    16. SELECT * FROM test4;
    17. SELECT * FROM test3
    18. UNION ALL -- 去重合并
    19. SELECT * FROM test4;
    d60866d2a98e46beaf6cccce6362408e.png

    图解合并查询


    5.表的复制

    1. -- 表复制
    2. -- 自我复制
    3. CREATE TABLE test(
    4. id INT,
    5. `name` VARCHAR(23),
    6. age INT);
    7. INSERT INTO test
    8. VALUES(1,'阳阳',19),(2,'小赵',19),(3,'山鱼',20),(4,'浩浩',19);
    9. -- 把查询到的本表内容加入到本表完成自我复制
    10. INSERT INTO test
    11. SELECT * FROM test;
    12. DELETE FROM test
    13. -- 去除表中重复记录
    14. -- 1.创建一个新表
    15. CREATE TABLE test2(
    16. id INT,
    17. `name` VARCHAR(23),
    18. age INT);
    19. -- 2.把旧表的数据复制到新表上
    20. INSERT INTO test2(id,`name`,age)
    21. SELECT DISTINCT id,`name`,age FROM test; -- 此处在查找时去重
    22. -- 3.删除旧表
    23. DROP TABLE test;
    24. -- 4.新表改名
    25. RENAME TABLE test2 TO test;

    二、外连接

            前面我们学习的查询,是利用where子句对两张或多张表,形成的笛卡尔集进行筛选,根据关联条件,显示所有匹配的记录,匹配不上的不显示。

            不过这样就会造成一个问题,比如当要求:列出部门名称(dept表)和这些部门的员工名称和工作(emp表),同时要求显示那些没有员工的部门。由于我们是在多表形成的笛卡尔集中匹配关联条件进行筛选,因此我们无法显示出没有员工的部门,也无法显示出没有部门的员工。

            由此我们引出了外连接。

            1.左外连接

            如果左侧的表完全显示我们就说是左外连接。

            用法:SELECT ... FROM  表1  LEFT JOIN  表2  ON  条件

    代码演示如下:

    1. -- 创建测试表
    2. CREATE TABLE stu(
    3. id INT,
    4. `name` VARCHAR(23));
    5. INSERT INTO stu
    6. VALUES(1,'Newbniz'),(2,'Mike'),(3,'john');
    7. CREATE TABLE grade2(
    8. id INT,
    9. score DOUBLE);
    10. INSERT INTO grade2
    11. VALUES(1,59.9),(2,33);
    12. -- 左外连接
    13. -- 一般情况下
    14. SELECT * FROM stu,grade2
    15. WHERE stu.id=grade2.id;
    16. -- 使用左外连接
    17. SELECT *
    18. FROM stu LEFT JOIN grade2
    19. ON stu.id = grade2.id;
    20. SELECT * FROM stu;
    21. SELECT * FROM grade2;

     

     

    83f3031553ff4f61acde1cd50f7439dc.png

    图解左外连接

     


            2.右外连接

            如果右侧的表完全显示我们就说是右外连接。

            用法:SELECT ... FROM  表1  RIGHT JOIN  表2  ON  条件

    代码演示如下:

    1. -- 创建测试表
    2. CREATE TABLE stu(
    3. id INT,
    4. `name` VARCHAR(23));
    5. INSERT INTO stu
    6. VALUES(1,'Newbniz'),(2,'Mike'),(3,'john');
    7. CREATE TABLE grade1(
    8. id INT,
    9. score DOUBLE);
    10. INSERT INTO grade1
    11. VALUES(1,59.9),(2,33),(3,45),(4,78);
    12. -- 右外连接
    13. -- stu表和grade1表演示左外连接
    14. SELECT * FROM stu;
    15. SELECT * FROM grade1;
    16. -- 一般情况下
    17. SELECT * FROM stu,grade1
    18. WHERE stu.id=grade1.id;
    19. -- 使用右外连接
    20. SELECT *
    21. FROM stu RIGHT JOIN grade1
    22. ON stu.id = grade1.id;

     

     

    416292536fcc4891a9cc254b4830f0cf.png

    图解右外连接

     


    三、最后的话

     

    ✨  原创不易,还希望各位大佬支持一下


    👍  点赞,你的认可是我创作的动力!


    ⭐️  收藏,你的青睐是我努力的方向!


    ✏️  评论,你的意见是我进步的财富!

     

  • 相关阅读:
    PHP语言基础知识,电商API代码生成
    redis集群系列三
    酷早报:6月23日Web3加密行业每日新闻汇总
    【Leetcode刷题Python】96. 不同的二叉搜索树
    使用DBeaver自动生成ER图
    flutter 系列之:flutter 中的幽灵offstage
    仓颉语言HelloWorld内测【仅需三步】
    微软语音扩展全球语言支持,发布160个新声音
    mysql如何复制一张表的数据到新的表
    Spring Boot是什么呢?
  • 原文地址:https://blog.csdn.net/qq_64449257/article/details/126781303