Mysql连接和子查询

Sql92语法:仅仅支持内连接

①等值连接

②非等值连接

③自连接

Sql99语法(推荐使用):支持内连接+外连接+交叉连接

按功能分类:

        内连接:

                        1.等值连接

                        2.非等值连接

                        3.自连接

        外连接:

                        1.左外连接

                        2.右外连接

                        3.全外连接(Mysql不支持)

        交叉连接: 

Sql92标准:

语法: select  字段1,字段2  from 表1 t1,表2 t2 where 条件;  

1.等值连接

案例1:查询员工名和对应的部门名 
SELECT last_name,department_name from employees e,departments d WHERE e.department_id=d.department_id;

Mysql连接和子查询

案例2:查询员工名,工种号,工种名

SELECT last_name,job_title,j.job_id FROM employees e,jobs j where e.job_id=j.job_id;

employees表中也有job_id而jobs表中也有job_id,会有歧义,因此需要指明是哪个表中的job_id

Mysql连接和子查询

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

SELECT last_name,department_name FROM employees e,departments  d WHERE e.department_id=d.department_id AND commission_pct is not null; 

Mysql连接和子查询

可以跟筛选:

案例4:查询城市名中第二个字母为o的部门名和城市名

SELECT department_name,city from departments d,locations l WHERE d.location_id=l.location_id AND  city LIKE '_o%';

Mysql连接和子查询

可以跟分组:

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

SELECT count(*),city from departments d,locations l WHERE d.location_id=l.location_id GROUP BY city;

Mysql连接和子查询  

可以跟排序:

案例6:查询每个工种的工种名和员工的个数,并且按员工个数降序

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

Mysql连接和子查询

可以实现多表的连接:

案例7:查询员工名、部门名和所在的城市

SELECT last_name,department_name,city FROM employees e,departments d,locations l where e.department_id=d.department_id AND d.location_id = l.location_id;

Mysql连接和子查询

2.非等值连接

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

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

Mysql连接和子查询

3.自连接(顾明思议自己连接自己)

案例:查询员工的名称和上级的名称

SELECT e.last_name,m.last_name FROM employees e,employees m WHERE e.manager_id=m.employee_id;

 Mysql连接和子查询

Mysql连接和子查询

1. 显示所有员工的姓名,部门号和部门名称

SELECT last_name,d.department_id,department_name FROM employees e,departments d where e.department_id=d.department_id;

Mysql连接和子查询

2.查询90号部门员工的job_id和90号部门的location_id

SELECT job_id,location_id FROM employees e,departments d WHERE e.department_id=d.department_id  AND  d.department_id='90';

Mysql连接和子查询

3.查询所有有奖金的员工的last_name,depart_name,location_id,city

 SELECT last_name,department_name,l.location_id,city FROM employees e,departments d,locations l WHERE e.department_id=d.department_id AND d.location_id=l.location_id and commission_pct is not null;

Mysql连接和子查询

4.选择city在Toronto工作的员工的last_name,job_id,department_id,department_name

SELECT last_name,job_id,d.department_id,department_name,city FROM employees e,departments d,locations l WHERE e.department_id=d.department_id AND d.location_id=l.location_id AND city='Toronto';
Mysql连接和子查询

5.查询每个工种、每个部门的部门名、工种名和最低工资

SELECT job_title,department_name,MIN(salary) FROM employees e,departments d,jobs j WHERE e.department_id=d.department_id AND e.job_id=j.job_id GROUP BY department_name,job_title;

Mysql连接和子查询

6. 查询每个国家下的部门个数大于2的国家编号

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

Mysql连接和子查询

7. 选择指定员工的姓名,员工号,以及他的管理者的姓名和员工号

SELECT e.last_name employees,e.employee_id 'Emp#',m.last_name 'Manager',m.employee_id 'Mgr#' FROM employees e,employees m where e.manager_id=m.employee_id;

Mysql连接和子查询

总结:
            1.多表连接的结果是它们之间的交集
            2.n个表连接需要n-1个条件
            3.一般要为表起别名
            4.可以跟分组函数、分组查询、排序等组合使用


Sql99语法:

语法:

        select 查询列表  from 表1 别名 [ 连接类型] join 表2 别名 on 连接条件

        [ where 筛选条件] [ group by 分组] [having 筛选条件] [order by 排序列表]

分类:

        1.内连接:inner join

        2.外连接:

                ①左外连接:left [outer] join

                ②右外连接:right [outer] join

                ③全外连接:full [outer] join

         3.交叉连接:cross join

内连接:

1.等值连接

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

SELECT last_name,department_name FROM employees e INNER join departments d on e.department_id=d.department_id;

Mysql连接和子查询

 案例2:查询名字中包含e的员工名和工种名(刷选)

SELECT last_name,job_title FROM employees e INNER JOIN jobs j on e.job_id=j.job_id WHERE job_title LIKE '%e%';

Mysql连接和子查询

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

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

Mysql连接和子查询

案例4:查询那个部门的部门员工个数>3的部门名和员工个数,并按个数降序(排序)

SELECT COUNT(*),department_name FROM employees e LEFT JOIN departments d on e.department_id=d.department_id GROUP BY department_name ORDER BY COUNT(*) desc; 

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

SELECT last_name,department_name,job_title FROM employees e LEFT JOIN departments d on e.department_id=d.department_id LEFT JOIN jobs j on e.job_id=j.job_id ORDER BY department_name desc;

Mysql连接和子查询

2.非等值连接

案例:查询工资级别个数>2的个数,并且按工资级别排序

SELECT COUNT(*),grade_level FROM employees e INNER JOIN job_grades jg on salary BETWEEN lowest_sal AND highest_sal GROUP BY grade_level;

Mysql连接和子查询

3.自连接

案例:查询员工的名字、上级的名字

SELECT e.last_name employees,m.last_name manager FROM employees e INNER JOIN employees m on e.manager_id=m.employee_id;

Mysql连接和子查询

 外连接:

1.查询主表中的所有记录,如果从表有和它匹配的则显示,如果没有和它匹配的则显示null。

2.查询结果=内连接结果+主表中有从表中没有的记录

左外连接:left左边的是主表

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

SELECT department_name FROM departments d LEFT JOIN employees e on d.department_id=e.department_id where e.employee_id is null;

Mysql连接和子查询

右外连接:right右边的是主表

全外连接:mysql暂时不支持,查询结果=内联结果+表1中有表2中没有+表2中有表1中没有的

交叉连接:笛卡尔积

Mysql连接和子查询

 1.SELECT beauty.*,boys.boyName FROM beauty LEFT JOIN boys on beauty.boyfriend_id = boys.id WHERE beauty.id>3;

Mysql连接和子查询

2.SELECT DISTINCT city,department_id FROM locations l LEFT JOIN departments d on d.location_id=l.location_id WHERE department_id is NULL;

Mysql连接和子查询

3.SELECT e.*,department_name FROM employees e LEFT JOIN departments d on e.department_id=d.department_id WHERE department_name in ('SAL','IT');

Mysql连接和子查询

子查询:

含义:出现在其他语句中的select语句,被称为一个子查询,外围的查询语句被称为主查询或者外查询

按子查询出现的位置进行一个分类:

1.放在select后面,只能是标量子查询(一行一列)

2.放在from后面,作为数据源

        支持表子查询

3.放在where/having后面

        标量子查询

        行子查询

        列子查询

4.放在exists后面(相关子查询)

        表子查询

按结果集行列数不同进行一个分类:

1.标量子查询(一行一列)

2.列子查询(一列多行)

3.行子查询(一行多列)

4.表子查询(结果集)

一、where/having后面的子查询

特点:

①使用一对()包含

②一般放在条件的右侧

③标量子查询一般搭配单行操作符(<,>,<=,>=,<>)使用

④列子查询一般搭配多行操作符(in,any/some,all)使用

#标量子查询

案例1:谁的工资比Abel高

SELECT last_name FROM employees where salary>(SELECT salary FROM employees WHERE last_name='Abel');

Mysql连接和子查询

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

SELECT 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');

Mysql连接和子查询

案例3:返回公司工资最少的员工的last_name,job_id和salary

SELECT last_name,job_id,salary FROM employees WHERE salary=(SELECT MIN(salary) FROM employees); 

Mysql连接和子查询

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

SELECT department_id,MIN(salary) FROM employees GROUP BY department_id HAVING MIN(salary)>(SELECT MIN(salary) FROM employees WHERE department_id='50');

Mysql连接和子查询

列子查询: 

一般与in,any/some,all搭配使用

案例1:返回location_id是1400或1700的部门中的所有员工姓名

SELECT last_name FROM employees WHERE department_id in (SELECT department_id FROM departments WHERE location_id in ('1400','1700'));

Mysql连接和子查询

 案例2:返回工种比job_id为'IT_PROG'所有工资都低的员工的员工号、姓名、job_id、以及salary

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

Mysql连接和子查询

行子查询:

案例1:查询员工编号最小并且工资最高的员工信息

SELECT e.* FROM employees e where (employee_id,salary)=(SELECT MIN(employee_id),MAX(salary) FROM employees);

Mysql连接和子查询

 二、放在select后面的标量子查询

案例1:查询每个部门的员工个数
SELECT d.*,(SELECT COUNT(*) FROM employees e WHERE e.department_id = d.department_id ) FROM departments d;

Mysql连接和子查询

 案例2:查询员工号为102的部门名

SELECT (SELECT d.department_name FROM departments d LEFT JOIN employees e on e.department_id=d.department_id WHERE e.employee_id='102');

Mysql连接和子查询

三、放在from后面

案例1:查询每个部门的平均工资的工资等级

SELECT grade_level,mm.d_id,mm.ag_sal FROM job_grades,(SELECT avg(salary) ag_sal,department_id d_id FROM employees GROUP BY department_id) mm WHERE mm.ag_sal  BETWEEN   lowest_sal AND  highest_sal;

Mysql连接和子查询

案例2: 查询员工号为102的部门名

SELECT d.department_name FROM departments d,(SELECT department_id d_id FROM employees WHERE  employee_id='102') mm WHERE d.department_id=mm.d_id; 

Mysql连接和子查询

四、exists后面(相关子查询)

案例1:查询所有员工的部门名

SELECT DISTINCT department_name FROM departments d WHERE EXISTS (SELECT * FROM employees e WHERE e.department_id=d.department_id);

Mysql连接和子查询

Mysql连接和子查询

 1.查询和Zlotkey相同部门的员工姓名和工资

SELECT last_name,salary FROM employees WHERE department_id = (SELECT department_id FROM employees WHERE last_name='Zlotkey');

Mysql连接和子查询

 2.查询工资比公司平均工资高的员工的员工号,姓名和工资

SELECT employee_id,last_name,salary FROM employees WHERE salary>(SELECT avg(salary) FROM employees);

Mysql连接和子查询

 3.查询各部门中工资比本部门平均工资高的员工的员工号,姓名和工资

SELECT  e.employee_id,e.last_name,e.salary FROM employees e,(SELECT avg(salary) ag_sal,department_id FROM employees GROUP BY department_id) mm WHERE mm.department_id =e.department_id AND salary > mm.ag_sal;

Mysql连接和子查询

 4.查询和姓名中包含字母u的员工在相同部门的员工的员工号和姓名

SELECT employee_id,last_name FROM employees WHERE department_id in (SELECT DISTINCT department_id FROM employees WHERE last_name LIKE '%u%');
Mysql连接和子查询

5.查询在部门的location_id为1700的部门工作的员工的员工号

SELECT employee_id from employees WHERE department_id in (SELECT DISTINCT d.department_id FROM departments d WHERE d.location_id='1700'); 

Mysql连接和子查询

 6.查询管理者是K_ing的员工姓名和工资

SELECT last_name,salary FROM employees WHERE manager_id in (SELECT employee_id FROM employees WHERE last_name='K_ing');

Mysql连接和子查询

 7.查询工资最高的员工的姓名,要求first_name和last_name显示为一列,列名为姓.名

SELECT CONCAT(last_name,first_name) FROM employees WHERE salary = (SELECT MAX(salary) FROM employees);

Mysql连接和子查询

                        

上一篇:权限系统设计


下一篇:SQLAlchemy 多对多