1. and 和 or 的优先级问题
在where字句中出现多个and or ,and的优先级 先于or的优先级,
select * from table1 where id = 1 or id =2 and name = 'zhouy'
结果: id =1 或 id=2 && name = 'zhouy'
在出现多个and, or 可以使用括号()改变优先级,捋清楚条件
select * from table2 where (id=1 or id =2) and name ='zhouy'
结果:id =1 and name ='zhouy' 或 id=2 and name ='zhouy'
2. 多表join
fulljoin: mysql不支持fulljoin,不过可以使用union来合并left join 和 right join 模拟fulljoin
cross join : 交叉连接,得到的结果是两个表的乘积,即笛卡尔积
实际上,在MySql中(仅限于Mysql),CROSS JOIN 与 INNER JOIN 的表现是一样的,在不指定 ON 条件得到的结果都是笛卡尔积,反之取得两个表完全匹配的结果。并且cross join 和 inner join 的 cross 和 inner 都可以省略。
下面查询的结果是相同的:
... FROM table1 INNER JOIN table2
... FROM table1 CROSS JOIN table2
... FROM table1 JOIN table2
性能优化
显示 inner join VS 隐式 inner join
select * from table a inner join table b on a.id = b.id; //显示 inner join
select a.*, b.* from table a, table b where a.id = b.id; //隐式 inner join
我在数据库中比较(10w数据)得之,它们用时几乎相同
left join/right join vs inner join
尽量用inner join,避免 left join 和 null, 在使用 left join (或right join) 时,应该知道的几点:
1. on 和 where的执行顺序
on ( from A left join B on ),ON条件用来决定从B表中检索数据的条件,如果B表中没有满足条件的行,将生成
一行null的数据,注意在匹配阶段where后面的条件,不会被使用,仅在匹配阶段完成后,where条件才会被使用。
select * from A
inner join B on B.name = A.name
left join C on C.name = B.name
left join D on D.id = C.id
where C.status>1 and D.status=1;
VS
select * from A
inner join B on B.name = A.name
left join C on C.name = B.name and C.status>1
left join D on D.id = C.id and D.status=1
从上面例子可以看出,尽可能满足ON的条件,而少用Where的条件。从执行性能来看第二个显然更加省时。
2. ON 和 where 的区别
mysql> SELECT * FROM product LEFT JOIN product_details
ON (product.id = product_details.id)
AND product_details.id=2;
+----+--------+------+--------+-------+
| id | amount | id | weight | exist |
+----+--------+------+--------+-------+
| 1 | 100 | NULL | NULL | NULL |
| 2 | 200 | 2 | 22 | 0 |
| 3 | 300 | NULL | NULL | NULL |
| 4 | 400 | NULL | NULL | NULL |
+----+--------+------+--------+-------+
rows in set (0.00 sec)
mysql> SELECT * FROM product LEFT JOIN product_details
ON (product.id = product_details.id)
WHERE product_details.id=2;
+----+--------+----+--------+-------+
| id | amount | id | weight | exist |
+----+--------+----+--------+-------+
| 2 | 200 | 2 | 22 | 0 |
+----+--------+----+--------+-------+
row in set (0.01 sec)
第一个on条件,决定了left join product_details中匹配的数据行,而where条件则是left join product_details后,从所有的数据行中找出匹配的数据
3. 尽量避免使用自查询,使用join
性能这玩意儿,更多的提现在数据量比较大的时候,应该避免使用复杂的子查询
不推荐:
insert into t1(a1) select b1 from t2 where not exists(select 1 from t1 where t1.id = t2.r_id);
推荐:
insert into t1(a1)
select b1 from t2
left join (select distinct t1.id from t1 ) t1 on t1.id = t2.r_id
where t1.id is null;
数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户。
在使用left jion时,on和where条件的区别如下:
1、on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。
2、where条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有left join的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。
假设有两张表:
表1:tab1
id size
10
20
30
表2:tab2
size name
AAA
BBB
CCC
两条SQL:
1、select * from tab1 left join tab2 on tab1.size = tab2.size where tab2.name='AAA'
2、select * from tab1 left join tab2 on tab1.size = tab2.size and tab2.name='AAA'
第一条SQL的过程:
1、中间表
on条件:
tab1.size = tab2.size
tab1.id tab1.size tab2.size tab2.name
10 10 AAA
20 20 BBB
20 20 CCC
30 (null) (null)
2、再对中间表过滤
where 条件:
tab2.name='AAA'
tab1.id tab1.size tab2.size tab2.name
10 10 AAA
第二条SQL的过程:
1、中间表
on条件:
tab1.size = tab2.size and tab2.name='AAA'
(条件不为真也会返回左表中的记录) tab1.id tab1.size tab2.size tab2.name
10 10 AAA
20 (null) (null)
30 (null) (null)
其实以上结果的关键原因就是left join,right join,full join的特殊性,
不管on上的条件是否为真都会返回left或right表中的记录,full则具有left和right的特性的并集。
而inner jion没这个特殊性,则条件放在on中和where中,返回的结果集是相同的。
3. STRAIGHT_JOIN
STRAIGHT_JOIN:由于默认情况下MySQL在进行表的联结的时候会先读入左表,当使用了这个参数后MySQL将会先读入右表,这是个MySQL的内置优化参数,大家应该在特定情况下使用,譬如已经确认右表中的记录数量少,在筛选后能大大提高查询速度。
Note:
在MySQL5.0以后,运算顺序得到了重视,所以对多表的联结查询可能会错误以子联结查询的方式进行。譬如你需要进行多表联结,因此你输入了下面的联结查询:
SELECT t1.id,t2.id,t3.id FROM t1,t2 LEFT JOIN t3 ON (t3.id=t1.id) WHERE t1.id=t2.id;
但是MySQL并不是这样执行的,其后台的真正执行方式是下面的语句:
SELECT t1.id,t2.id,t3.id FROM t1,( t2 LEFT JOIN t3 ON (t3.id=t1.id) ) WHERE t1.id=t2.id;
这并不是我们想要的效果,所以我们需要这样输入:
SELECT t1.id,t2.id,t3.id FROM (t1,t2) LEFT JOIN t3 ON (t3.id=t1.id) WHERE t1.id=t2.id;
最后,记录下多表连接的常见场景:
inner join(等值连接) 只返回两个表中联结字段相等的行
left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录
right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录
INNER JOIN 语法:
INNER JOIN 连接两个数据表的用法:
SELECT * FROM 表1 INNER JOIN 表2 ON 表1.字段号=表2.字段号
INNER JOIN 连接三个数据表的用法:(一个join 一个join 理顺)
SELECT * FROM (表1 INNER JOIN 表2 ON 表1.字段号=表2.字段号) INNER JOIN 表3 ON 表1.字段号=表3.字段号
或
select * from (表1 inner join 表2 on 表1.字段号=表2.字段号) inner join 表3 on 表2.字段号 = 表3.字段号
INNER JOIN 连接四个数据表的用法:
SELECT * FROM ((表1 INNER JOIN 表2 ON 表1.字段号=表2.字段号) INNER JOIN 表3 ON 表1.字段号=表3.字段号) INNER JOIN 表4 ON Member.字段号=表4.字段号
INNER JOIN 连接五个数据表的用法:
SELECT * FROM (((表1 INNER JOIN 表2 ON 表1.字段号=表2.字段号) INNER JOIN 表3 ON 表1.字段号=表3.字段号) INNER JOIN 表4 ON Member.字段号=表4.字段号) INNER JOIN 表5 ON Member.字段号=表5.字段号
转载自:
https://www.cnblogs.com/ClassNotFoundException/p/5991834.html
https://www.cnblogs.com/qiaoyihang/p/6401280.html,推荐阅读