可能会出现的错误:
笛卡尔积的错误会在下面条件下产生:
省略多个表的连接条件(或关联条件)
连接条件(或关联条件)无效
所有表中的所有行互相连接
如何避免: 可以在 WHERE 加入有效的连接条件。
在 WHERE子句中写入连接条件。
代码举例:
#多表查询如何实现
#出现笛卡尔积的错误
SELECT employee_id,department_name
FROM employees,departments;#查询出2889条数据------错误的
#每个员工都与每个部门匹配过----------------缺少多表的连接条件
SELECT employee_id,department_name
FROM employees CROSS JOIN departments;#------------------缺少连接条件#多表查询的正确方法,需要有连接条件
SELECT employee_id,department_name
FROM employees,departments
#多表的连接条件--------------------写在where中
WHERE employees.`department_id` = departments.`department_id`;
注意点:
》区分重复的列名
多个表中有相同列时,必须在列名之前加上表名前缀。
》利用表的别名,简化。(在from中表名的后面给表取一个简单的别名)
》如果有n个表实现多表查询,则需要至少n-1个连接条件
连接的分类
》等值连接:使用等号的方式进行连接
》非等值连接:不使用等号的方式进行连接
》非自连接:不同表的连接
》自连接:同一张表,自己连接自己
》内连接:
合并具有同一列的两个以上的表的行, 结果集中不包含一个表与另一个表不匹配的行
》外连接:
两个表在连接过程中除了返回满足连接条件的行以外还返回左(或右)表中不满足条件的
行 ,这种连接称为左(或右) 外连接。没有匹配的行时, 结果表中相应的列为空(NULL)。
如果是左外连接,则连接条件中左边的表也称为 主表 ,右边的表称为 从表 。
如果是右外连接,则连接条件中右边的表也称为 主表 ,左边的表称为 从表 。
》满外连接:即连接条件中左边的表,也条件中右边的表
》自然连接:NATURAL JOIN
内连接,不同表,有相同列名;自动将所有的不同表中相同列名连接
---------------------------不够灵活
代码举例:
#自然连接与USING连接
SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
ON e.`department_id` = d.`department_id`
AND e.`manager_id` = d.`manager_id`;
#等同与
SELECT employee_id,last_name,department_name
FROM employees e NATURAL JOIN departments d;
#将自然连接等价为等值连接,自动查询两张表中相同的字段--------------------将所有相同的列都算进来了,不够灵活
》USING连接:JION USING
内连接,不同表,有相同列名,在USING后面的括号中写明连接条件所需的列(该列需要时不同表中同名的列)
代码举例:
#USING连接
SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
ON e.`department_id` = d.`department_id`;
#等价与
SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
USING (department_id);
#当两个字段(属于不同表的)同名时-------------连接条件
不同点:
自然连接 NATURAL JOIN 不同的是,USING 指定了具体的相同的字段名称,你需要在 USING
的括号 () 中填入要指定的同名字段。同时使用 JOIN...USING 可以简化 JOIN ON 的等值连接。
内连接(INNER JOIN)的实现
语法:
SELECT 字段列表
FROM A表 INNER JOIN B表
ON 关联条件
WHERE 等其他子句;
代码举例:
#SQL99语法如何实现内连接
#两个表的
SELECT last_name,department_name
FROM employees e JOIN departments d
ON e.`department_id`=d.`department_id`;#三个表的----JOIN…ON 只能一对一对的使用不能 JOIN…ON…ON/JOIN …JOIN ..ON 连用
SELECT last_name,department_name,city
FROM employees e JOIN departments d
ON e.`department_id`=d.`department_id`
JOIN locations l
ON d.`location_id`=l.`location_id`;
也可以使用 :where 连接条件
SELECT employee_id,department_name
FROM employees,departments
WHERE employees.`department_id` = departments.`department_id`;
外连接(OUTER JOIN)的实现
#SQL92语法实现外连接:使用 + ------------------MySQL不支持SQL92语法中的外连接写法!
#SQL99语法中使用JOIN...ON 的方式实现多表的查询。这种方式也能解决外哦连接问题。MySQL支持此写法
左外连接(LEFT OUTER JOIN)
语法:
#实现查询结果是A
SELECT 字段列表
FROM A表 LEFT JOIN B表
ON 关联条件
WHERE 等其他子句;
右外连接(RIGHT OUTER JOIN)
语法:
FROM A表 RIGHT JOIN B表
ON 关联条件
WHERE 等其他子句;
代码举例:
#左外连接
SELECT employee_id,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id`=d.`department_id`;#右外连接
SELECT employee_id,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id`=d.`department_id`;
满外连接(FULL OUTER JOIN)
满外连接的结果 = 左右表匹配的数据 + 左表没有匹配到的数据 + 右表没有匹配到的数据。
SQL99是支持满外连接的。使用FULL JOIN 或 FULL OUTER JOIN来实现。
需要注意的是,MySQL不支持FULL JOIN,但是可以用 LEFT JOIN UNION RIGHT join代替。
UNION的使用
合并查询结果 利用UNION关键字,可以给出多条SELECT语句,并将它们的结果组合成单个结果集合并。
注意:
》此时,两个表对应的列数和数据类型必须相同,并且相互对应。各个SELECT语句之间使用UNION或UNION ALL关键字分隔。
》UNION:UNION 操作符返回两个查询的结果集的并集,去除重复记录。
UNION ALL:UNION ALL操作符返回两个查询的结果集的并集。对于两个结果集的重复部分,不去重。
格式:
SELECT column,... FROM table1
UNION [ALL]
SELECT column,... FROM table2
代码举例
SELECT employee_id,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id`=d.`department_id`
UNION ALL
SELECT employee_id,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id`=d.`department_id`
WHERE e.`department_id`IS NULL;
总结:
表连接的约束条件可以有三种方式:WHERE, ON, USING
WHERE:适用于所有关联查询
ON :只能和JOIN一起使用,只能写关联条件。虽然关联条件可以并到WHERE中和其他条件一起
写,但分开写可读性更好。
USING:只能和JOIN一起使用,而且要求两个关联字段在关联表中名称一致,而且只能表示关联字
段值相等