Mysql 中Left/Right join on後面and和where條件查詢的差異-Mysql SQL運算子是有優先順序
一、Mysql中Left/Right join on後面and和where條件查詢的差異
1、建兩張測試表,一張商戶定義表、一張商戶操作狀態明細表
1)商戶定義表
CREATE TABLE hope.merchant (
MERCHANT_id varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
2)商戶操作明細表
CREATE TABLE trade_info (
MERCHANT_NO varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
TRADE_STATUS varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
CREATE_TIME datetime DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
2.測試Left/Right join on後面and和where條件查詢的差異
普通left join演示
select a.MERCHANT_id,b.MERCHANT_NO,b.TRADE_STATUS from hope.merchant a left join hope.trade_info b
on a.MERCHANT_id=b.MERCHANT_NO;
select count(1) from hope.merchant a left join hope.trade_info b
on a.MERCHANT_id=b.MERCHANT_NO;--》82行資料
結果:可以看到,部分商戶在某段時間內事沒有任何操作的,所以,左表hope.merchant的商戶,沒有對應的操作,會用Null補足。
1)Left/Right join on後面帶and
select a.MERCHANT_id,b.MERCHANT_NO,b.TRADE_STATUS,b.CREATE_TIME from hope.merchant a left join hope.trade_info b
on a.MERCHANT_id=b.MERCHANT_NO and b.CREATE_TIME>'2018-12-19 19:00:00';
select count(1) from hope.merchant a left join hope.trade_info b
on a.MERCHANT_id=b.MERCHANT_NO and b.CREATE_TIME>'2018-12-19 19:00:00'; ----》69行資料
2)Left/Right join on後面帶where
select a.MERCHANT_id,b.MERCHANT_NO,b.TRADE_STATUS,b.CREATE_TIME from hope.merchant a left join hope.trade_info b
on a.MERCHANT_id=b.MERCHANT_NO where b.CREATE_TIME>'2018-12-19 19:00:00';
select count(1) from hope.merchant a left join hope.trade_info b
on a.MERCHANT_id=b.MERCHANT_NO where b.CREATE_TIME>'2018-12-19 19:00:00'; --》43行資料
3)對比結果
語句一是on and ,一句是 on where,下的條件類似,但是結果卻是完全不同。帶where的過濾掉了左連線中左表沒有任何操作記錄的商戶號,
但是使用and的卻沒有,並得到了我想要的結果。Why???
二、Mysql 運算子是有優先順序
1.總結SQL優先順序
大家可能看出一些規律,在on的情況下and(或者or)與on同時對前面的集合起作用,而存在where的時候,先對集合進行on條件的抽取,在根據where的條件進行抽取.這是個值得注意的地方.
說下原因:
(1)ON後面的篩選條件主要是針對的是關聯表【而對於主表篩選條件不適用】;
(2)對於主表的篩選條件應放在where後面,不應該放在ON後面;
(3)對於關聯表我們要區分對待。如果是要條件查詢後才連線應該把查詢件放置於ON後;如果是想再連線完畢後才篩選就應把條件放置於where後面;
(4)對於關聯表我們其實可以先做子查詢再做join。
2.總結sql型別,儘量不寫子查詢
1)對於關聯表我們其實可以先做子查詢再做join,此SQL執行3.5秒
select MERCHANT_ID,case when rait is null then 0 else rait end
from (
select MERCHANT_ID,
TRUNCATE(count(case when c.trade_status ='SUCCESS' then 1 else null end)*100/count(case when c.trade_status !='FAILED' then 1 else null end),2) rait
from ifpay_ccpay.merchant a left join (
select * from ifpay_ccpay.trade_info b where b.CREATE_TIME > date_add(now(), interval - 30 minute)
and b.method='H5') c on a.MERCHANT_ID=c.MERCHANT_NO group by a.MERCHANT_ID) d;
2)不做子查詢執行14ms
select MERCHANT_ID,case when rait is null then 0 else rait end
from (
select MERCHANT_ID,
TRUNCATE(count(case when b.trade_status ='SUCCESS' then 1 else null end)*100/count(case when b.trade_status !='FAILED' then 1 else null end),2) rait
from ifpay_ccpay.merchant a left join ifpay_ccpay.trade_info b on a.MERCHANT_ID=b.MERCHANT_NO
and b.CREATE_TIME > date_add(now(), interval - 30 minute)
and b.method='H5' group by a.MERCHANT_ID) D;