MySQL连接的种类,JOIN左边(前边)的表是左边,右边(后边)的是右表
- 逗号:做笛卡尔集连接
- INNER JOIN: 如果表中有至少一个匹配,则返回行
- LEFT JOIN: 即使右表中没有匹配,也从左表返回所有的行
- RIGHT JOIN: 即使左表中没有匹配,也从右表返回所有的行
- NATURAL JOIN
- NATURAL LEFT JOIN
- NATURAL RIGHT JOIN
- CROSS JOIN
注:
- MySQL不支持FULL JOIN(只要其中一个表中存在匹配,就返回行),可以结合使用UNION、LEFT/RIGHT JOIN来实现;
- MySQL中LEFT/INNER JOIN还可以写成LEFT/INNER OUTER JOIN;
- CROSS JOIN在标准SQL中是不带ON子句的,作用是生成笛卡尔积,在MySQL中CROSS JOIN后带ON子句时,CROSS会被忽略,就相当于JOIN;
- 不使用ON子句时,JOIN和INNER JOIN和CROSS JOIN和逗号是等价的,做笛卡尔积;
- 使用ON子句时,INNER/LEFT/RIGHT JOIN不会生成笛卡尔集,直接根据条件生成临时表
- 逗号操作符和其他几种连接操作符的优先级不同,尽量不要同时使用避免出错。
- 使用逗号连接加where子句和使用INNER JOIN加ON子句效果一样
- join、inner join、cross join支持on和using语法,逗号不支持on和using语法
多表查询的过程:
- 由多张表生成一张临时表(有on子句时由on子句中的条件生成)
- 使用JOIN的方式以及ON子句后面的条件进行筛选
- 使用使用WHERE子句后面的条件筛选
- 使用GROUP BY条件分组
- 使用HAVING+聚合函数筛选
- 使用ORDER BY排序
- 使用LIMIT筛选
假设对表a、b、c进行联合查询
提示错误:Unknown column 'xxx' in 'on clause'
原因是FROM后面的两张表没有使用括号包裹起来
--错误的写法
select * from a,b left join c on 条件 where 条件
--正确的写法
select * from (a,b) left join c on 条件 where 条件
如果左连接时某个字段为空,就让他等于另外一个字段,使用IFNULL()
SELECT
h.id AS id,
h.goods_id AS goodsId,
g.goods_advert AS goodsAdvert,
IFNULL(aos.activity_price,g.sell_price) AS sellPrice,--注意g.sell_price不能用别名price代替
g.goods_name AS goodsName,
g.logo_url AS logoUrl,
g.is_delivery AS isDelivery,
g.sell_price AS price
FROM
(tb_house h,
tb_goods g)
LEFT JOIN tb_aos_goods_rt aos ON h.goods_id = aos.goods_id
WHERE
1 = 1
AND h.member_id = 107
AND h.goods_id = g.id
AND h. STATUS = 1
ORDER BY
h.create_date DESC
如果某条数据的aos.activity_price为null,最后的结果集要以sellPrice排序,ORDER by后面应该写别名sellPrice而不是写aos.activity_price
CROSS JOIN的用法:http://www.yiibai.com/mysql/cross-join.html
左右连接能否同时使用
SQL 定义了两种不同语法方式去表示"连接"。首先是"显式连接符号",它显式地使用关键字 JOIN,其次是"隐式连接符号",它使用所谓的"隐式连接符号"。隐式连接符号把需要连接的表放到 SELECT 语句的 FROM 部分,并用逗号隔开。这样就构成了一个"交叉连接",WHERE 语句可能放置一些过滤谓词(过滤条件)。那些过滤谓词在功能上等价于显式连接符号. SQL 89标准只支持内部连接与交叉连接,因此只有隐式连接这种表达方式;SQL 92标准增加了对外部连接的支持,这才有了JOIN表达式。
逗号连接加where子句和inner join加on子句的异同
在查询条件相同时它们的查询结果是相同的,但是查询的过程不完全相同;
使用逗号操作符加where子句:首先生成笛卡尔积,因为在没有on子句时,逗号和CROSS JOIN是相同的,然后通过条件去过滤。
使用inner join加on子句:直接通过条件去过滤生成临时表,不会生成笛卡尔集,速度更快
开启优化参数后MySQL会自动优化,通常使用,不会造成资源浪费;不使用逗号,全部使用JOIN是最好的,这样既不会因为运算符优先级不同而出错,也不会因为没有开启优化参数而造成资源浪费。
join的方式不同,cross join生成的是先生成笛卡尔集,然后on连接条件被视为了filter用于数据过滤,inner join是直接基于join condition做连接,生成的join集合就是最终的输出结果,产生的中间数据更小。实际上MySQL优化器会将这两条查询都优化成同一种join方式,比如merge join或者nested loop join,如果你没有开启对应的优化参数,那么MySQL只有傻傻的去按指定的方式去做join
查询条件放在ON后面和放在WHERE后面有什么差异
有上可知,在没有ON时,INNER JOIN和CROSS JOIN是一样的 ,所以推荐使用INNER JOIN ON代替逗号加WHERE;
ON条件是生成临时表时使用的条件,与JOIN的类型有关,不同类型产生的临时表也不同,WHERE条件时在临时表生成之后进行筛选的条件,在LEFT或RIGHT JOIN中条件是不能随便放的
在where后面有多个条件时使用加个1=1的原因