链接查询html
主要分为内链接(等值链接,非等值链接,自链接),外链接(左外链接,右外链接,全外链接),交叉链接三大类。mysql
sql92标准中: from 表1,表2 ,表3 where 条件1 and 条件2 and 题目条件
sql99标准中: from 表1 join 表2 on 条件1 join 表3 on 条件2 where 题目条件sql
内链接:表之间经过某种关系创建链接来进行关联查询。其中自链接是针对自身的两次表的查询,必须指定别名来区别查询时使用哪一次的表数据库
外链接函数
外链接主要用于添加 where语句后筛选:(主表中有可是副表中没有)'s 主表中的对象。不添加where 语句则筛选出:以主表为主的主副链接表优化
select 字段 from table_m left [outer] join table_vice1 on 表间关联条件1 [left join table_vice2 on 关联条件2 ...] where condition_clause;#条件语句通常为 ... is [not] null .
与查询有关的关键字段属于哪一个表,哪一个表就是主表。code
例如:查询没有奖金的员工姓名,此时员工表e就为主表,奖金表s为副表。
SELECT e.e_name FROM e LEFT JOIN s ON e.e_id=s.e_id WHERE s.e_id IS NULL;
htm
right [outer] join 相似同理(主副表位置调换)对象
full [outer] join 全链接 :两表交集(经过内链接可实现)+左外链接(A主B副)+左外链接(B主A副)blog
交叉链接:交叉链接是笛卡尔积在sql中的实现。 关键字:cross join
子查询(内查询)
联合查询
一些思考点
(1) . group by语句的使用场景。
多表链接查询时,若主查询的select字段中含有 count, sum, average等聚合函数,以 "查询每一个部门的员工个数" 为例:
若count字段做为外查询字段而直接显式存在,须要使用group by 语句呈现分类效果
select d.* ,count(e.department_id) as 员工个数 from departments d left join employees e on e.department_id =d.department_id group by d.department_id; /* count(e.department_id) 不该书写为count(d.department_id),也不该书写为count(*),二者都会致使本没有员工的部门员工个数计为1。应充分理解外链接查询结果的含义,从而理解外查询count(para)字段中para的不一样所对应的含义,当para为“*”时,是计算列数,空值也会计算在内并计为1,故当要求“没有员工的部门的员工个数既要正确书写为0,又不能省略员工个数为0的部门(简单的在e表中按照d_id分类count查询)”时正确操做应为:d表为主 e表为副 group by(d.department_id) 查询 count(e.department_id) */
假如无group by 子句,则查询结果将始终为单行,无论与count(*)同时查询的还有什么字段。如:
或是(不合题,仅做示例):
若count字段做为子查询(内查询)隐式存在
select d.* ,(select count(*) from employees e where e.department_id = d.department_id ) 员工个数 from departments d ;
此时为内外嵌套,外在表现为单表查询。
(2). Exist 子查询的使用。(未充分理解)
博客园'半壁江山'总结详细,可供参考 关键字: 执行顺序&规则,boolean,应用场景,效率。
(3). 如题:查询各部门工资比所在部门平均工资高的员工的员工号,姓名,薪资
① 第一想法: 内链接+where clause 子查询 关联三表 ,结果正确,表面也易理解。
select d.department_id , d.department_name ,e.employee_id , e.last_name , e.salary from employees e join departments d on e.department_id = d.department_id where salary > (select avg(salary) from employees em where em.department_id = e.department_id);
② 将各部门的平均工资经过 select 子查询 命名'建表' ——davg。employees,departments,davg 三表左外链接 。
select d.department_id , d.department_name ,e.employee_id , e.last_name , e.salary , davg.a as 该部平均工资 from departments as d left join employees as e on e.department_id = d.department_id left join (select department_id , avg(salary) a from employees group by department_id ) as davg on davg.department_id = d.department_id where e.salary > davg.a order by davg.a,e.salary;
固然由于where语句的限制,某些没有员工的部门没有呈现出来。(固然题目也没有这种要求,可是理论上d为主表进行 left join 查询时全部的部门都应该呈现,即便对应的其他表为皆为null值)。经过删除where 限制,并按department_id DESC排列能够看到实际上三表链接后是存在这样的数据的。
... on davg.department_id = d.department_id order by d.department_id DESC limit 0,50;
Limit [ offset ,] row_count ;
The first argument specifies the offset of the first row to return, and the second specifies the maximum number of rows to return. The offset of the initial row is 0 (not 1)
Limit row_count OFFSET offset
③ 固然也能够省略select 字段中的department_name 字段,从而免去departments表与另外两表的链接。只将e表与davg表(经过select 子查询命名的各部门平均薪资表)内链接或者外链接。代码略。
(4) 如题:查询平均工资最低的部门信息。
错解1: 子查询所构建的表不识别,失效
SELECT d.*, davg.a FROM departments AS d RIGHT JOIN ( SELECT department_id, avg( salary ) a FROM employees WHERE department_id IS NOT NULL GROUP BY department_id ) AS davg ON davg.department_id = d.department_id WHERE davg.a = ( SELECT MIN( davg.a ) FROM davg );
Table 'my_employees.davg' doesn't exist
。正解2: 可使用 order by + limit 的结合语句来实现查询效果
SELECT d.*, davg.a FROM departments AS d RIGHT JOIN ( SELECT department_id, avg( salary ) a FROM employees WHERE department_id IS NOT NULL GROUP BY department_id ) AS davg ON davg.department_id = d.department_id #内链接更简? ORDER BY davg.a ASC LIMIT 1;# 可修改行数肯定是否最低值只有一个。
该策略一样适用于: 其余有关 '最低,最高 '类字眼的查询 (在此不考虑效率问题)
正解3:复杂嵌套1
SELECT d.* FROM departments d WHERE department_id = ( #此处 '=' 换用 'in' 更好 SELECT davg.department_id FROM ( SELECT department_id, avg(salary) a FROM employees GROUP BY department_id ) AS davg WHERE a = ( SELECT MIN(该部平均工资) FROM (SELECT avg(salary) AS 该部平均工资 FROM employees GROUP BY department_id ) AS davg # 'AS davg' 必须有,语法要求。尽管前面select min(arg)不加davg也OK ) ) # 两个子查询字段中的别名‘davg’互不影响,固然若写成不同更易理解。
此类嵌套查询解题思路:
①明确各个层次,清晰定义。② 从最内层,最小解题单元开始,逐步完善。③ 耐心,耐心。
疑问:对于mysql中重复出现的语句有没有相似命名定义方法。
正解4:复杂嵌套2
SELECT d.* FROM departments d WHERE department_id = ( #此处 '=' 换用 'in' 更好 SELECT department_id FROM employees e GROUP BY department_id HAVING AVG(salary) = ( SELECT MIN( a ) FROM ( SELECT AVG(salary) a FROM employees GROUP BY department_id ) AS davg ) )
该解不一样与正解3的地方在于Having 子句的使用替代了where子查询嵌套,须要理解的是:
要真正理解group by 子句的所带来的效果/意义,以及各子句之间的执行顺序:
① group by 子句的使用必然与' 需使用聚合类函数的需求'有关(想不出没有使用聚合类函数的需求仍然使用group by 子句的),但: 并不意味着聚合类函数必定[显式]出如今select 语句的字段中,它也能够出如今 having ,where 等子句中(执行顺序在它以后的就OK)
② 执行顺序:from 子句,join ta_name on cond类 子句 , group by 子句 , having 子句 , where 子句,select 子句 ,order by 子句,limit 子句。
解5 存储过程?视图?