• 05.多表查询


    多个表中查询数据

    多表查询的错误示范

    # 现有表 employees、departments表
    # 查询last_name为Abel的人在哪个城市工作
    SELECT employee_id,department_name FROM employees,departments;
    

    image-20220311003817348

    # 这种查询方式的查询结果是笛卡尔积,查询结果数量是 表1数量*表2数量
    # 等同于如下的交叉连接查询方式
    SELECT employee_id,department_name FROM employees CROSS JOIN departments;
    

    多表查询的正确方式(需要有连接条件)

    # 带连接条件的多表查询方式
    SELECT employee_id,department_name 
    FROM employees,departments 
    WHERE employees.department_id = departments.department_id;
    # 如果查询语句中多个表中有相同字段,必须指明此字段所在的表
    SELECT employees.employee_id,departments.department_name,employees.department_id
    FROM employees,departments
    WHERE employees.department_id = departments.department_id;
    # 从sql优化的角度,建议多表查询,每个字段都指明其所在的表
     
    # 可以给表起别名,在SELECT和WHERE中使用表的别名,而且一旦有了别名,在SELECT和WHERE中必须使用别名
    # 这里注意了,虽然可以给字段起别名但是只能在ORDER BY中使用不能在WHERE中使用
    SELECT emp.employee_id,dept.department_name,emp.department_id
    FROM employees emp,departments dept
    WHERE emp.department_id = dept.department_id;
    # 但是如果起了别名之后还是用表名就会报错
    SELECT emp.employee_id,dept.department_name,emp.department_id
    FROM employees emp,departments dept
    WHERE emp.department_id = departments.department_id;
    # 报错 > 1054 - Unknown column 'departments.department_id' in 'where clause'
    

    image-20220311004310452

    # 如果要查询n个表中的数据,至少需要n-1个连接条件
    SELECT emp.employee_id,dept.department_name,emp.department_id,city
    FROM employees emp,departments dept,locations l
    WHERE emp.department_id = dept.department_id
    AND l.location_id = dept.location_id;
    

    image-20220311005818726

    多表查询的分类

    按照不同的角度可以分为三类

    等值连接和非等值连接

    等值连接和非等值就是连接条件的不同

    # 上面的内容都是等值连接
    # 下面介绍非等值连接
    # 查询每个员工工资的等级
    SELECT e.employee_id,e.salary,j.grade_level
    FROM employees e,job_grades j
    WHERE e.salary >= j.lowest_sal AND e.salary <= j.highest_sal
    

    image-20220311010434012

    自连接和非自连接

    # 自连接就是查询的数据在自己的表中
    # 举个例子:一张员工表,查询每个员工的管理者,员工表中的管理者id与员工id对应
    # 两张表都是employees,起不同的别名实现自连接查询
    SELECT emp.employee_id,emp.first_name,emp_manager.employee_id manager_id,emp_manager.first_name manager_name
    FROM employees emp, employees emp_manager
    WHERE emp.manager_id = emp_manager.employee_id;
    

    image-20220311011250486

    内连接和外连接

    简单地说,内连接就是两张表的交集,上面介绍的都是内连接

    外连接就是除了两张表的交集还要左表或者右表不匹配的行
    外连接分为:左外连接、右外连接、满外连接

    # 内连接 这里只能查询出106条数据,因为有一台数据的department_id为null
    SELECT employee_id,department_name 
    FROM employees,departments 
    WHERE employees.department_id = departments.department_id;
    
    # 外连接
    # 查询所有员工的的department_id
    # 左外连接(包含左表的全部数据)
    SELECT employee_id,department_name 
    FROM employees LEFT JOIN departments 
    ON employees.department_id = departments.department_id;
    
    # 右外连接(包含右表的全部数据)  可以省略RIGHT OUTER JOIN
    SELECT employee_id,department_name 
    FROM employees RIGHT JOIN departments 
    ON employees.department_id = departments.department_id;
    
    # 满外连接, MySQL不能通过FULL OUTER JOIN 实现满外连接
    # MySQL需要借助UNION的使用 
    # UNION 去重结果
    # UNION 不去重结,单纯的把两张表加起来
    SELECT employee_id,department_name 
    FROM employees LEFT JOIN departments 
    ON employees.department_id = departments.department_id
    UNION
    SELECT employee_id,department_name 
    FROM employees RIGHT JOIN departments 
    ON employees.department_id = departments.department_id;
    

    7种JOIN的实现

    SQL的JOIN有其中情况分别如下:

    在这里插入图片描述

    # 左外连接
    SELECT employee_id,department_name 
    FROM employees LEFT JOIN departments 
    ON employees.department_id = departments.department_id;
    

    1007094-20190715191748302-838005539.png

    # 左外连接去掉中间重合部分
    SELECT employee_id,department_name 
    FROM employees LEFT JOIN departments 
    ON employees.department_id = departments.department_id
    WHERE employees.department_id IS NULL;
    

    1007094-20190715192717507-1315818425.png

    # 内连接
    SELECT employee_id,department_name 
    FROM employees JOIN departments 
    ON employees.department_id = departments.department_id;
    

    1007094-20190715192020606-1587521340.png

    # 右外连接
    SELECT employee_id,department_name 
    FROM employees RIGHT JOIN departments 
    ON employees.department_id = departments.department_id;
    

    1007094-20190715191929542-156753267.png

    # 右外连接去掉中间重合部分
    SELECT employee_id,department_name 
    FROM employees RIGHT JOIN departments 
    ON employees.department_id = departments.department_id
    WHERE employees.department_id IS NULL;
    

    img

    # 全外连接,有多种写法
    # 左外连接+右外连接 只能用UNION不能用UNION ALL,因为有重复部分需要去重
    SELECT employee_id,department_name 
    FROM employees LEFT OUTER JOIN departments 
    ON employees.department_id = departments.department_id
    UNION
    SELECT employee_id,department_name 
    FROM employees RIGHT OUTER JOIN departments 
    ON employees.department_id = departments.department_id;
    
    # 左外连接+ (右外连接-重叠部分)可以用UNION或者UNION ALL
    SELECT employee_id,department_name 
    FROM employees LEFT OUTER JOIN departments 
    ON employees.department_id = departments.department_id
    UNION
    SELECT employee_id,department_name 
    FROM employees RIGHT JOIN departments 
    ON employees.department_id = departments.department_id
    WHERE employees.department_id IS NULL;
    
    # (左外连接-重叠部分) + 右外连接 可以用UNION或者UNION ALL
    SELECT employee_id,department_name 
    FROM employees LEFT OUTER JOIN departments 
    ON employees.department_id = departments.department_id
    WHERE departments.department_id IS NULL
    UNION
    SELECT employee_id,department_name 
    FROM employees RIGHT JOIN departments 
    ON employees.department_id = departments.department_id;
    
    # (左外连接-重叠部分) + (右外连接-重叠部分) + 重叠部分 可以用UNION或者UNION ALL
    SELECT employee_id,department_name 
    FROM employees LEFT OUTER JOIN departments 
    ON employees.department_id = departments.department_id
    WHERE departments.department_id IS NULL
    UNION
    SELECT employee_id,department_name 
    FROM employees RIGHT JOIN departments 
    ON employees.department_id = departments.department_id
    WHERE employees.department_id IS NULL
    UNION
    SELECT employee_id,department_name 
    FROM employees JOIN departments 
    ON employees.department_id = departments.department_id;
    

    1007094-20190715192657988-2106915309.png

    SQL99语法特性

    自然连接

    自然连接可以不用指定字段相同,自动匹配相同的字段

    # 原来的写法
    SELECT employee_id,last_name,department_name
    FROM employees e JOIN departments d
    ON e.`department_id` = d.`department_id`
    AND e.`manager_id` = d.`manager_id`;
    
    # 使用自然连接的写法
    SELECT employee_id,last_name,department_name
    FROM employees NATURAL JOIN departments;
    

    USING

    
    USING ()# 原来的写法
    SELECT employee_id,last_name,department_name
    FROM employees e JOIN departments d
    ON e.`department_id` = d.`department_id`
    AND e.`manager_id` = d.`manager_id`;
    
    # 使用自然连接的写法
    SELECT employee_id,last_name,department_name
    FROM employees JOIN departments
    USING (department_id,manager_id)
    
  • 相关阅读:
    JAVA--导数到Mongodb
    关于jquery的事件委托-bind,live,delegate,on的区别发展
    cookies localStorage和sessionStorage的区别
    px em 和rem之间的区别
    js中string常用方法
    js中number常用方法
    json格式常用操作
    Node.js到底是做什么的?这是我看到最好的解释了
    数组常用操作方法
    JQuery.Ajax()的data参数类型
  • 原文地址:https://www.cnblogs.com/jiangblog/p/15996013.html
Copyright © 2020-2023  润新知