zoukankan      html  css  js  c++  java
  • 自连接和子查询

    SQL SELECT(复杂查询)之 自连接 & 子查询 解析

    一、自连接

    概念:把一张表 当做多个表使用

    语法:

    select ...
    from 表 a(别名)
    join 表 b(别名)
    
    on a.字段=b.字段
    
    注意:
    
    自连接也可以是 内连接也可以是外连接
    自己与一张与自己完全一样的从表建立关系 进行连接查询

    以下举例所用表

    employees表:字段如下

    employee_id, first_name, last_name, email, phone_number

    job_id, salary, commission_pct, manage_id, department_id

    案例: xx员工 为 xx上司 工作

    分析:

    employees表:字段如下

    employee_id, first_name, last_name, email, phone_number

    job_id, salary, commission_pct, manage_id, department_id

    manage_id 是员工id为emplo_id的领导者id 其对应的一条记录也是

    employees表中的一条普通员工记录

    /*
    进一步分析:
    
    1.相当于查询员工名和上司名
    2.将自己(employees表)当做两个表, m和e
    
    */
    #分析1
    //相当于从employee表中查找 经过匹配后 得到这个员工的领导  
       manager_id 再把它从这个表中查出来
    
    SELECT e.`first_name` 员工名,m.`first_name` 老板名
    FROM employees e
    JOIN employees m  ON e.`manager_id`=m.`employee_id`
    
    #分析2 通过自己与自己内连接 跟自连接 一样
    SELECT CONCAT(e.`first_name`,' work for ',m.`first_name`)  info
    FROM employees e
    JOIN employees m  ON e.`manager_id`=m.`employee_id`

    二、子查询

    (一)子查询

    分类:

    单行子查询: 子查询的结果集是一行

    多行子查询: 子查询的结果集是多行

    注意事项:
        子查询要包含在括号内。
    
        将子查询放在比较条件的右侧。
    
        单行操作符对应单行子查询,多行操作符对应多行子查询。
    单行操作符:
        > < >= <= = <>
    多行操作符:
        in(重点)、any(任意一个)、all(所有的)
        not in

    1、单行子查询

     比较的对象是唯一的一个而不是一个范围集合
    
    • 1
    • 2

    1.案例:谁的工资比 Abel 高?

    /*
        分析1: 求出Abel的工资
        分析2: 筛选employees表,判断 salary > Abel的工资
    */
    
    求出Abel的工资,得到一个值
    SELECT salary FROM employees WHERE last_name = 'Abel';
    
    筛选employees表,判断 salary > Abel的工资
    SELECT * FROM employees WHERE salary>11000;
    
    
    结合以上两部分析将第一个分析所得结果作为被比较的条件对象
    
    SELECT * 
    FROM employees 
    WHERE salary>(
        SELECT salary 
        FROM employees 
        WHERE last_name = 'Abel'
    );

    2.案例:返回job_id与141号员工相同,salary比143号员工多的员工

        姓名,job_id 和工资
    
         /*
         分析1:先查询 141 号员工的job_id
               以及 143号员工的salary
         */
    
    1》先查询 141 号员工的job_id
       以及 143号员工的salary
    
    
    SELECT job_id 
    FROM employees 
    WHERE employee_id = 141
    
    SELECT salary 
    FROM employees 
    WHERE employee_id = 143
    
    2》结合以上两部将其作为被比较的条件对象筛选指定的员工
    
    SELECT last_name 姓名,job_id ,salary 工资
    FROM employees
    WHERE job_id =(
        SELECT job_id 
        FROM employees 
        WHERE employee_id = 141
    
    ) AND salary>(
        SELECT salary 
        FROM employees 
        WHERE employee_id = 143
    )

    3 子查询中使用了组函数。

    以下举例所用表

    employees表:字段如下

    employee_id, first_name, last_name, email, phone_number

    job_id, salary, commission_pct, manage_id, department_id

    案例 返回工资最少的员工的last_name,job_id和salary

    SELECT last_name,job_id,salary 
    FROM employees
    WHERE salary=(
    
        //把如下语句获取的值作为salary比较的条件对象
        SELECT MIN(salary) FROM employees
    );
    
    SELECT * FROM employees;//查看结果有没有改变

    4 子查询中用到了having

    案例:查询最低工资大于50号部门最低工资的部门id和其最低工资

    /*
        分析1:先查询50号部门的最低工资
        分析2:每个部门的部门id和其最低工资
        分析3:筛选看哪个部门的最低工资大于分析1的结果
    
    */
    #分析1
    SELECT MIN(salary) 
    FROM employees
    WHERE department_id=50
    
    #分析2
    SELECT MIN(salary) ,department_id
    FROM employees
    GROUP BY department_id
    
    #分析3
    
    SELECT MIN(salary) ,department_id
    FROM employees
    GROUP BY department_id
    HAVING MIN(salary)>(
        SELECT MIN(salary) 
        FROM employees
        WHERE department_id=50
    
    );

    非法使用单行子查询,其实就是 子查询结果集中返回的是多行 
    SELECT MIN(salary) ,department_id 
    FROM employees 
    GROUP BY department_id 
    HAVING MIN(salary)>( 
    SELECT salary 
    FROM employees 
    WHERE department_id>50//返回的是多个值对象

    );

    单行子查询的结果集中出现 null的问题

    SELECT MIN(salary) ,department_id
    FROM employees
    GROUP BY department_id
    HAVING MIN(salary)>(
        SELECT salary 
        FROM employees
        WHERE department_id>300 //结果为null
    
    );

    单行子查询的结果集多列的问题

    SELECT MIN(salary) ,department_id
    FROM employees
    GROUP BY department_id
    HAVING MIN(salary)>(  //到这一步 用于比较的MIN(salary)有很多个 不
        SELECT MIN(salary),department_id 
        FROM employees
        WHERE department_id=50  //50号部门最低工资
    
    );

    二、多行子查询 
    1.题目:

    返回其它部门中比job_id为‘IT_PROG’部门任一工资低的员工的员

    工号、姓名、job_id 以及salary

    提示:比最高工资低 就行

         /*
         分析1: 先查询 job_id为‘IT_PROG’部门任一工资
         分析2: 查询员工号、姓名、job_id 以及salary  比分析1的 结果中任意一个都低的
    
         */
    
         1》. 先查询 job_id为‘IT_PROG’部门任一工资
    
         SELECT salary 
         FROM employees
         WHERE job_id = 'IT_PROG'
    
    
         2 》查询员工号、姓名、job_id 以及salary  比分析1的 结果中任意一个都低的
    
         SELECT employee_id,last_name,job_id,salary
         FROM employees
         WHERE salary<ANY(
                SELECT salary 
             FROM employees
             WHERE job_id = 'IT_PROG'
    
         )

    2.题目:返回其它部门中比job_id为‘IT_PROG’部门所有工资都低的员工

    的员工号、姓名、job_id 以及salary

    提示:相当于比 最小的工资还要低

         SELECT employee_id,last_name,job_id,salary
         FROM employees
         WHERE salary<ALL(
                SELECT salary 
             FROM employees
             WHERE job_id = 'IT_PROG'
    
         )
    

    3.题目:返回其它部门中工资和 job_id为‘IT_PROG’部门的随便一个工资 相同 的员工

    SELECT employee_id,last_name,job_id,salary
         FROM employees
         WHERE salary NOT IN(
                SELECT salary 
             FROM employees
             WHERE job_id = 'IT_PROG'
         )
    
    语法:
    
    in(值1,值2,值3)
    salary =值1 or salary=值2 or salary=值3
    
  • 相关阅读:
    IIS:日志代码分析
    SQL:查找被锁的表,以及锁表的SQL语句(重点推荐)
    SQL 2000/2005/2008 收缩日志方法
    SQL SERVER:使用工具观察与分析数据库中锁信息
    C# : Post 接收或发送XML
    WCF:没有终结点在侦听可以接受消息的*这通常是由于不正确的地址或者 SOAP操作导致的。
    SQL2005 遍历表插入
    SQL2005:SQL Server 2005还原数据库时出现“不能选择文件或文件组XXX_log用于此操作的解决办法
    C#:安装Windows服务,动态指定服务名及描述
    IE6与 javascript:void(0)
  • 原文地址:https://www.cnblogs.com/yunfeioliver/p/7883618.html
Copyright © 2011-2022 走看看