MySQL子查询_分页查询_联合查询

进阶7:子查询

 

含义

        一条查询语句中又嵌套了另一条完整的select语句,其中被嵌套的select语句,称为子查询或内查询

        在外面的查询语句,称为主查询或外查询

 

特点:

        1、子查询都放在小括号内

        2、子查询可以放在

        from后面仅仅支持子查询、

        select后面支持标量子查询(单行)、

        where后面having后面标量子查询,列子查询

,但一般放在条件的右侧,也可以放在

exists后面(相关子查询)表子查询

        3、子查询优先于主查询执行,主查询使用了子查询的执行结果

        4、子查询根据查询结果的行数不同分为以下两类:

        ① 单行子查询

               结果集只有一行

               一般搭配单行操作符使用:> < = <> >= <=

               非法使用子查询的情况:

               a、子查询的结果为一组值

               b、子查询的结果为空

              

        ② 多行子查询/列子查询(一列多行)

               结果集有多行

              

        行子查询,多行多列

 

 

Where或者having后面

标量子查询(单行子查询)

列子查询(多行子查询)

行子查询(多列多行)

特点:子查询都放在小括号内,子查询一般防止条件的右侧,标量子查询一般搭配单行操作符   > < >= ….

列子查询一般搭配多行操作符号一般搭配多行操作符使用:any/some、all、in、not in

               in: 属于子查询结果中的任意一个就行

               any和all往往可以用其他查询代替

标量子查询

#谁的工资比Abel高

  1. 查询Abel工资高
  2. 然后找比这个标量大的

mysql> select last_name from employees where salary>(select salary from employees where last_name='Abel');

 

#找job_id 与141号员工相同,salary比143号员工多的员工 姓名,job_id和工资

mysql> select job_id,salary from employees where job_id=(select job_id from employees where employee_id =141) andd salary>(select salary from employees where employee_id =143);

+----------+---------+

| job_id   | salary  |

+----------+---------+

| ST_CLERK | 3200.00 |

 

#返回公司工资最少的员工的last_name,job_id和salary

查询公司的最低工资

mysql> select last_name,job_id,salary from employees where salary=(select min(salary) from employees);

+-----------+----------+---------+

| last_name | job_id   | salary  |

+-----------+----------+---------+

| Olson     | ST_CLERK | 2100.00 |

+-----------+----------+---------+

mysql> select last_name,job_id,salary from employees order by salary asc limit 1;

+-----------+----------+---------+

| last_name | job_id   | salary  |

+-----------+----------+---------+

| Olson     | ST_CLERK | 2100.00 |

+-----------+----------+---------+

 

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

mysql> select department_id,min(salary) from employees group by department_id having min(salary)>(select min(salaary) from employees where department_id=50);

+---------------+-------------+

| department_id | min(salary) |

+---------------+-------------+

|          NULL |     7000.00 |

|            10 |     4400.00 |

|            20 |     6000.00 |

|            30 |     2500.00 |

|            40 |     6500.00 |

+---------------+-------------+

 

列子查询

 

in/not in   等于列表中的任意一个

any/some    和子查询返回的某一个比较

all         和子查询返回的所有值比较

>any  可以替换成>min

>all   可以替换成>max

#返回location_id 是1400或者1700的部门中的所有员工姓名

  1. 查询location 1400或者1700

mysql> select last_name,department_id from employees where department_id in(select distinct department_id from departments s where location_id in(1400,1700));

+------------+---------------+

| last_name  | department_id |

+------------+---------------+

| Hunold     |            60 |

| Ernst      |            60 |

 

mysql> select last_name,e.department_id from employees e join departments d on e.department_id=d.department_id where d.location_id in((1400,1700);

 

返回其他部门中比job_id 为’IT_PROG’部门任一工资低的员工号、姓名、job_id以及salary    任一不是任意

 

mysql> select employee_id,last_name,job_id,salary from employees where salary<any(select salary from employees where job_id='IT_PROG')) and job_id!='IT_PROG';

 

mysql> select employee_id,last_name,job_id,salary from employees where salary<(select max(salary) from employees where job_id='IT_PROGG') and job_id!='IT_PROG';

 

行子查询  一行多列或者多行多列

查询员工编号最小且工资最高的员工信息(不一定存在)

可以分开来查  

两个条件都是等于(相同的关系)

mysql> select * from employees where(employee_id,salary)=(select min(employee_id),max(salary)from employees);

+-------------+------------+-----------+-------+--------------+---------+----------+----------------+------------+---------------+---------------------+

| employee_id | first_name | last_name | email | phone_number | job_id  | salary   | commission_pct | manager_id | department_id | hiredate            |

+-------------+------------+-----------+-------+--------------+---------+----------+----------------+------------+---------------+---------------------+

|         100 | Steven     | K_ing     | SKING | 515.123.4567 | AD_PRES | 24000.00 |           NULL |       NULL |            90 | 1992-04-03 00:00:00 |

+-------------+------------+-----------+-------+--------------+---------+----------+----------------+------------+---------------+---------------------+

 

 

select后面仅仅支持标量子查询

查询每个部门的员工数

 

 

mysql> select d.*,(select count(*) from employees e where e.department_id=d.department_id) nums from departments d;

+---------------+-----------------+------------+-------------+------+

| department_id | department_name | manager_id | location_id | nums |

+---------------+-----------------+------------+-------------+------+

|            10 | Adm             |        200 |        1700 |    1 |

 

 

查询员工号=102的部门名

mysql> select (select department_name from departments d inner join employees e on d.department_id=e.department_id where employee_id=1102)name;

+------+

| name |

+------+

| Exe  |

+------+

1 row in set (0.00 sec)

 

 

from后面   子查询的表格充当数据源,必须起别名

查询每个部门的平均工资的工资等级

先查每个部门的平均工资

mysql> select ag.*,g.grade_level from (select avg(salary) ave,department_id from employees group by department_id) ag inner join job_grades g on ag.ave between lowest_sal and highest_sal;

+--------------+---------------+-------------+

| ave          | department_id | grade_level |

+--------------+---------------+-------------+

|  7000.000000 |          NULL | C           |

|  4400.000000 |            10 | B           |

|  9500.000000 |            20 | C           |

 

Exists后面相关子查询     0或者1,有没有值

mysql> select exists(select employee_id from employees);

+-------------------------------------------+

| exists(select employee_id from employees) |

+-------------------------------------------+

|                                         1 |

 

mysql> select exists(select employee_id from employees where salary=20000000);

+-----------------------------------------------------------------+

| exists(select employee_id from employees where salary=20000000) |

+-----------------------------------------------------------------+

|                                                               0 |

+-----------------------------------------------------------------+

 

查询有员工的部门名

mysql> select department_name from departments d where exists(select* from employees e where d.departmeent_id=e.department_id);

+-----------------+

| department_name |

+-----------------+

mysql> select department_name from departments where department_id in (select department_id from employees);

+-----------------+

| department_name |

+-----------------+

| Adm             |

 

 

子查询 测 试

 

#查询工资最低的员工信息: last_name, salary

 

mysql> select last_name,salary from employees where salary=(select min(salary) from employees);

 

+-----------+---------+

 

| last_name | salary  |

 

+-----------+---------+

 

| Olson     | 2100.00 |

 

+-----------+---------+

 

1 row in set (0.00 sec)

 

 

 

#查询平均工资最低的部门信息

 

mysql> select * from departments d where d.department_id=(select department_id from employees group by department_id having avg(salary)=(select min(ag) from ( select department_id,avg(salary) ag from employees group by department_id) ag_dep));

 

+---------------+-----------------+------------+-------------+

 

| department_id | department_name | manager_id | location_id |

 

+---------------+-----------------+------------+-------------+

 

|            50 | Shi             |        121 |        1500 |

 

+---------------+-----------------+------------+-------------+

 

1 row in set (0.00 sec)

 

 

 

这样很麻烦,所以可以用limit

 

mysql> select * from departments where department_id =(select department_id from employees group by department_id order by avg(salary) asc limit 1);

 

+---------------+-----------------+------------+-------------+

 

| department_id | department_name | manager_id | location_id |

 

+---------------+-----------------+------------+-------------+

 

|            50 | Shi             |        121 |        1500 |

 

+---------------+-----------------+------------+-------------+

 

1 row in set (0.00 sec)

 

 

 

#查询平均工资最低的部门信息和该部门的平均工资

 

mysql> select d.*,dv.ag from departments d inner join (select avg(salary) ag,department_id from employees group by department_id) dv on d.department_id=dv.department_id order by dv.ag limit 1;

 

+---------------+-----------------+------------+-------------+-------------+

 

| department_id | department_name | manager_id | location_id | ag          |

 

+---------------+-----------------+------------+-------------+-------------+

 

|            50 | Shi             |        121 |        1500 | 3475.555556 |

 

+---------------+-----------------+------------+-------------+-------------+

 

 

 

 

 

#查询平均工资最高的 job 信息

 

mysql> select * from jobs where job_id=(select job_id from employees group by job_id order by avg(salary) asc limit 1);

 

+----------+------------------+------------+------------+

 

| job_id   | job_title        | min_salary | max_salary |

 

+----------+------------------+------------+------------+

 

| PU_CLERK | Purchasing Clerk |       2500 |       5500 |

 

+----------+------------------+------------+------------+

 

1 row in set (0.00 sec)

 

 

 

#查询平均工资高于公司平均工资的部门有哪些?

 

 

 

mysql> select department_id from employees group by department_id having avg(salary)>(select avg(salary) from employees);

 

 

 

#查询出公司中所有 manager 的详细信息.

 

mysql> select * from employees where employee_id=any( select distinct manager_id from employees);

 

 

 

#各个部门中 最高工资中最低的那个部门的 最低工资是多少

 

 

 

mysql> select department_id,min(salary) from employees group by department_id having department_id=(select department_id from employees group by department_id order by max(salary) asc limit 1);

 

+---------------+-------------+

 

| department_id | min(salary) |

 

+---------------+-------------+

 

|            10 |     4400.00 |

 

+---------------+-------------+

 

#查询平均工资最高的部门的 manager 的详细信息: last_name, department_id, email, salary

 

 

 

mysql> select last_name,department_id,email,salary from employees where employee_id=(select manager_id from departments where department_id=(select department_id from employees grroup by department_id order by avg(salary) desc limit 1));

 

+-----------+---------------+-------+----------+

 

| last_name | department_id | email | salary   |

 

+-----------+---------------+-------+----------+

 

| K_ing     |            90 | SKING | 24000.00 |

 

+-----------+---------------+-------+----------+

 

 

 

上述方法三层嵌套子查询

 

 

 

下方法将两个表链接后将第一步作为条件

 

mysql> select last_name,d.department_id,email,salary from employees e inner join departments d on d.manager_id=e.employee_id where d.department_id=(select department_id from employees group by department_id order by avg(salary) desc limit 1);

 

+-----------+---------------+-------+----------+

 

| last_name | department_id | email | salary   |

 

+-----------+---------------+-------+----------+

 

| K_ing     |            90 | SKING | 24000.00 |

 

+-----------+---------------+-------+----------+

 

##进阶8:分页查询

 

 

应用场景:

 

        实际的web项目中需要根据用户的需求提交对应的分页查询的sql语句

 

语法:

 

        select 字段|表达式,...

        from 表

        【where 条件】

        【group by 分组字段】

        【having 条件】

        【order by 排序的字段】

        limit 【起始的条目索引,】条目数;

 

特点:

 

        1.起始条目索引从0开始

       

        2.limit子句放在查询语句的最后

       

        3.公式:select * from  表 limit (page-1)*sizePerPage,sizePerPage

        假如:

        每页显示条目数sizePerPage

        要显示的页数 page

 

查询前五条员工信息

mysql> select * from employees limit 0,5;

或者limit 5

 

##进阶9:联合查询

 

引入:

        union 联合、合并

 

语法:

 

        select 字段|常量|表达式|函数 【from 表】 【where 条件】 union 【all】

        select 字段|常量|表达式|函数 【from 表】 【where 条件】 union 【all】

        select 字段|常量|表达式|函数 【from 表】 【where 条件】 union  【all】

        .....

        select 字段|常量|表达式|函数 【from 表】 【where 条件】

 

特点:

 

        1、多条查询语句的查询的列数必须是一致的

        2、多条查询语句的查询的列的类型几乎相同

        3、union代表去重,union all代表不去重

 

原文地址:https://www.cnblogs.com/BetterThanEver_Victor/p/8752786.html