mysql查缺补漏(一) and or优先级和多表join

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,推荐阅读






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值