美文网首页
SQL-连接查询

SQL-连接查询

作者: 晓晓桑 | 来源:发表于2020-06-07 11:06 被阅读0次

    连接查询

    又叫:多表查询、多表连接
    含义:当查询的子都啊来自多个表时,就会用到连接查询

    笛卡尔乘积现象:表1有m行,表2有n行,结果=m*n
    发送原因:没有有效的连接条件
    如何避免:添加有效的连接条件

    连接查询分类:

    1. 按年代分类:
    • sql192标准:仅仅支持内连接
    • sql199标准【推荐】:支持内连接、外连接的左外连接、右外连接、交叉连接
    1. 按功能分类:
    • 内连接:等值连接、非等值连接、自连接
    • 外连接:左外连接、右外连接、全外连接
    • 交叉连接

    sql192和sql199

    功能:sql199支持的更多
    可读性:sql199实现连接条件和筛选条件的分离,可读性较高

    笛卡尔乘积现象出现:

    SELECT NAME,boyName FROM boys,beauty;

    避免笛卡尔乘积

    SELECT NAME,boyName FROM boys,beauty
    WHERE beauty.boyfriend_id = boys.id;

    sql192标准

    一.内连接 之 等值连接

    1. 多表等值连接的结果为多表的交集部分
    2. n表连接至少n-1和连接条件
    3. 多表的顺序没有要求
    4. 一般为表起个别名
    5. 可以搭配前面介绍的所有字句使用,比如排序、分组、筛选
    案例1 查询女神名和对应的男神名

    -- 会拿beauty表的boyfriend_id去匹配boys表的每一个id
    SELECT NAME,boyName FROM boys,beauty
    WHERE beauty.boyfriend_id = boys.id;

    案例2 查询员工名和对应的部门名

    SELECT last_name,department_name
    FROM employees,departments
    WHERE employees.department_id=departments.department_id;

    案例3 查询员工名、工种号、工种名

    SELECT last_name,employees.job_id,job_title -- 注意这边的job_id不知道是employees还是jobs的,有奇异,所以加个表名
    FROM employees,jobs
    WHERE employees.job_id=jobs.job_id; -- 2.两个表的顺序可以调换

    为表起名

    /*
    注意:
    如果为表起了别名,则查询的字段就不能使用原来的表名去限定了
    */

    上面案例3 可以写成

    SELECT last_name,e.job_id,job_title -- 起完别名之后,就不能写成employees.job_id了
    FROM employees AS e,jobs J -- as 或者空格 。
    WHERE e.job_id=J.job_id;

    添加筛选

    /*
    已经有where了,不能再加where了,加and
    */

    案例1 查询有奖金的员工名、部门名

    SELECT last_name,department_name
    FROM employees,departments
    WHERE employees.department_id=departments.department_id
    AND employees.commission_pct IS NOT NULL;

    案例2 查询城市名中第二个字符为o的部门m名和城市名

    SELECT departments.department_name,locations.city
    FROM departments,locations
    WHERE departments.location_id=locations.location_id
    AND city LIKE '_o%';
    -- AND SUBSTR(locations.city,2,1)='o';

    添加分组

    案例1 查询每个城市的部门个数

    SELECT COUNT(*),city
    FROM departments,locations
    WHERE departments.location_id=locations.location_id
    GROUP BY city;

    案例2 查询有奖金的每个部门名和部门的领导编号和部门的最低工资

    SELECT department_name,departments.manager_id,MIN(salary)
    FROM departments,employees
    WHERE departments.department_id=employees.department_id
    AND commission_pct IS NOT NULL
    GROUP BY department_name,departments.manager_id; -- 这两个都得加上

    添加排序

    查询每个工种的工种名和员工的个数,并且按照员工个数降序

    SELECT job_title,COUNT( * )
    FROM employees,jobs
    WHERE employees.job_id=jobs.job_id
    GROUP BY job_title
    ORDER BY COUNT(*) DESC;

    三表连接

    案例1 查询员工名、部门名、所在城市

    SELECT last_name,department_name,city
    FROM employees,departments,locations
    WHERE employees.department_id=departments.department_id
    AND departments.location_id=locations.location_id;-- 后面还可以加and 排序什么的

    内连接 之 非等值连

    /*
    非等值连 就是不是等值的连接,可以不等于,可能大于 小于。。。。
    */

    案例1:查询员工的工资和工资级别

    SELECT salary,grade_level
    FROM employees,job_grades
    WHERE salary BETWEEN job_grades.lowest_sal AND job_grades.highest_sal;

    内连接 之 自连接

    /*
    自己连接自己
    */

    案例 查询员工名和上级的名字

    -- 思路:在员工表 找到员工名,看他的上级的编号,根据上级的编号再在员工表查找这个编号对应的人。
    -- 因为上级是员工的一种

    SELECT e.last_name,e.employee_id,m.employee_id,m.last_name -- 员工名字 和领导的名字
    FROM employees e, employees m
    WHERE e.manager_id=m.employee_id;

    测试题

    测试1.显示员工表的最大工资,工资平均值

    SELECT MAX(salary),AVG(salary)
    FROM employees;

    测试2.查询员工表的employee_id,job_id,last_name,按department_id降序,salary升序

    SELECT employee_id,job_id,last_name
    FROM employees
    ORDER BY department_id DESC,salary ASC;

    测试3.查询员工表的job_id中包含a和e的,并且a在e的前面

    SELECT job_id
    FROM employees
    WHERE job_id LIKE '%a%e%';

    测试4.显示当前的日期,以及去前后空格,截取子字符串的函数

    SELECT SUBSTR(TRIM(NOW()))

    SELECT PASSWORD('xx'); -- 加密
    MD5('str');-- 加密

    测试5 查询每个国家下的部门个数大于2的国家编号

    SELECT country_id,COUNT()
    FROM departments d,locations l
    WHERE d.location_id=l.location_id
    GROUP BY country_id
    HAVING COUNT(
    )>2;

    测试6 选择指定员工的姓名,员工号,以及他的管理者的姓名和员工号

    SELECT e.locations,e.employee_id "Emp#",m.last_name,m.employee_id "Mgr#" -- 注意这个地方要加引号,因为#是特殊符号
    FROM employees e,employees m
    WHERE e.manager_id=m.employee_id
    AND e.last_name='Kochhar';

    sql99语法

    /*
    语法:
    select 查询列表
    from 表1 别名 【连接条件】
    john 表2 别名
    on 连接条件
    where 筛选条件
    group by 分组
    having 筛选条件
    order by 排序条件

    分类:
    内连接:inner
    外连接:左外:left 【outer】
    右外:right【outer】
    全外:full【outer】
    交叉连接:cross

    特点:
    1.添加排序、分组、筛选
    2.inner可以省略
    3.筛选条件放在where后面,连接条件放在on后面,提高分离性,便于阅读
    4.inner join连接和sql92的等值连接效果是一样的
    */

    一. 内连接

    SELECT 查询列表
    FROM 表1 别名
    inner join 表2 别名
    on 连接条件;

    分类:等值连接、非等值连接、自连接

    等值连接

    案例1.查询员工名、部门名

    SELECT last_name,department_name
    FROM employees e -- e和d表位置可以换
    INNER JOIN departments d
    ON e.department_id=d.department_id;

    案例2.查询名字中包含e的员工名和工种名(添加筛选)

    SELECT last_name,job_title
    FROM employees
    INNER JOIN jobs
    ON employees.job_id=jobs.job_id
    WHERE employees.last_name LIKE "%e%";

    案例3 查询部门个数>3的城市名和部门个数

    SELECT city,COUNT()
    FROM departments
    INNER JOIN locations
    ON departments.location_id=locations.location_id
    GROUP BY locations.city
    HAVING COUNT(
    )>3;

    案例4。查询哪个部门的员工个数>3的部门名和员工个数,并按照个数降序(添加顺序)

    SELECT department_name,COUNT()
    FROM employees
    INNER JOIN departments
    ON employees.department_id=departments.department_id
    GROUP BY department_name
    HAVING COUNT(
    )>3
    ORDER BY COUNT(*) DESC;

    案例5 查询员工名、部门名、工种名、并按照部门降序

    SELECT last_name,department_name,job_title
    FROM employees
    INNER JOIN departments ON employees.department_id=departments.department_id
    INNER JOIN jobs ON employees.job_id=jobs.job_id
    ORDER BY department_name DESC;

    二.非等值连接

    案例1:查询员工的工资和工资级别

    SELECT salary,grade_level
    FROM employees
    INNER JOIN job_grades
    ON employees.salary BETWEEN job_grades.lowest_sal AND job_grades.highest_sal;

    案例:查询每个工资级别的个数>20的个数,并且进行排序

    SELECT grade_level,COUNT()
    FROM job_grades
    INNER JOIN employees
    ON employees.salary BETWEEN job_grades.lowest_sal AND job_grades.highest_sal
    GROUP BY grade_level
    HAVING COUNT(
    )>20
    ORDER BY COUNT(*) DESC;

    自连接

    案例 查询姓名中包含k的员工名和上级的名字

    SELECT e.last_name 下属,m.last_name 上级
    FROM employees e
    INNER JOIN employees m
    ON e.manager_id=m.employee_id
    WHERE e.last_name LIKE '%k%';

    外连接

    /*
    应用场景:用于查询一个表中有,另一个表中没有的记录

    特点:

    1. 外连接的查询结果为主表中的所有记录。
    • 如果从表中有和他匹配的,则显示匹配的值;
    • 如果从表中没有和他匹配的,则显示null
      外连接查询结构=内连接结果+主表中有而从表没有的记录
    1. 左外连接中,left join左边的是主表,右外连接中,right join 右边的是主表
    2. 左外和右外交换两个表的顺序,可以实现同样的效果
      */
    引入:查询没有男朋友的女神名(男朋友不在男神表的女神名)

    -- 左外连接:
    SELECT beauty.name,boys.*
    FROM beauty
    LEFT OUTER JOIN boys
    ON beauty.boyfriend_id=boys.id
    WHERE boys.id IS NULL;

    -- 右外连接:
    SELECT beauty.name,boys.*
    FROM boys
    RIGHT OUTER JOIN beauty
    ON beauty.boyfriend_id=boys.id
    WHERE boys.id IS NULL;

    案例1 查询哪个部门没有员工

    -- 左外
    SELECT department_name
    FROM departments
    LEFT OUTER JOIN employees
    ON departments.department_id=employees.department_id
    WHERE employees.employee_id IS NULL;

    -- 右外
    SELECT department_name
    FROM employees
    RIGHT OUTER JOIN departments
    ON departments.department_id=employees.department_id
    WHERE employees.employee_id IS NULL;

    交叉连接

    -- 其实就是sql99语法里面的笛卡尔乘积
    -- 92语法直接用逗号的
    SELECT b.,bo.
    FROM beauty b
    CROSS JOIN boys bo;

    image.png image.png

    练习

    案例1 查询编号>3的女神的男朋友信息,如果有则列出详细,如果没有,用null填充

    SELECT boys.*,beauty.id
    FROM beauty
    LEFT OUTER JOIN boys
    ON boys.id=beauty.boyfriend_id
    WHERE beauty.id>3;

    案例2 查询哪个城市没有部门

    SELECT city
    FROM locations
    LEFT OUTER JOIN departments
    ON locations.location_id=departments.location_id
    WHERE departments.department_id IS NULL;

    案例3 查询部门名为SAL或IT的员工信息

    -- 分析: 如果sal或者it没有员工的话,用内连接就查不出来了。
    -- 下面是内连接 --有39条记录
    SELECT employees.*,departments.department_id
    FROM employees
    INNER JOIN departments
    ON employees.department_id=departments.department_id
    WHERE department_name='SAL' OR department_name='IT';

    -- 下面是外连接 有41条记录
    SELECT employees.*,departments.department_id
    FROM departments
    LEFT OUTER JOIN employees
    ON employees.department_id=departments.department_id
    WHERE departments.department_name IN('SAL','IT');-- WHERE department_name='SAL' OR department_name='IT';

    相关文章

      网友评论

          本文标题:SQL-连接查询

          本文链接:https://www.haomeiwen.com/subject/ogabzhtx.html