背景:公司業務線升級,更改業務線服務項名稱,牽扯到已發行的批次券名稱的更改,我的工單任務需要寫sql刷數據實現這些名稱的修改
涉及到的數據庫兩個數據表,我需要從A表中查詢出在B表中關聯的服務項只有1條數據並且所關聯的這個服務項爲所升級的業務線的服務項值所對應的批次,並且修改該A表中對應批次的名稱。
我想到的sql如下:
UPDATE `t_batch` SET batch_name=replace(batch_name,'AAA','BBB') WHERE batch_name LIKE '%AAA' and all_service = 0 and id IN
(SELECT batch_id FROM t_batch_service WHERE service_id = & AND batch_id in
(
SELECT batch_id from t_batch_service GROUP BY batch_id HAVING COUNT(*)=1
)
) and status in(*,*,*,*) ;
A | SELECT batch_id from mar_batch_service GROUP BY batch_id HAVING COUNT(*)=1 | 查詢出批次服務項列表中根據批次id分組後的總量爲1的批次id(爲外部嵌套查詢提供批次的過濾條件) |
B | SELECT batch_id FROM mar_batch_service WHERE service_id = * AND batch_id in(A) | 篩選出服務項id爲& 並且批次id在A條件中的批次id |
C | UPDATE `t_batch` SET batch_name=replace(batch_name,'AAA','BBB') WHERE batch_name LIKE '%AAA' and all_service = 0 and id IN(in) | 更新批次表中批次在B範圍內並且all_service = 0 的 名稱爲特定類型的批次名稱 |
後續發現這樣寫的sql很繁瑣原因有2
1.內層兩個自連接的sql可以合併成一個
2.這種in方法寫出的sql是慢sql類型,會造成mar_batch_service的鎖表,效率很低,
解決問題方法
問題 | 更改後 |
1.內層兩個自連接的sql可以合併成一個 |
UPDATE `t_batch` SET batch_name=replace(batch_name,'AAA','BBB') WHERE batch_name LIKE '%AAA' and all_service = 0 and id IN( |
2.這種in方法寫出的sql是慢sql類型,會造成mar_batch_service的鎖表,效率很低, | UPDATE t_batch a,(SELECT batch_id FROM t_batch_service where service_id=& GROUP BY batch_id HAVING COUNT(*)=1)b SET a.batch_name=replace(batch_name,'AAA','BBB') WHERE a.batch_name LIKE '%AAA' and a.all_service = 0 and a.status in(0,1,2,3,5) and a.id =b.batch_id; |
寫法2 | select count(*) from t_batch a,(SELECT batch_id FROM t_batch_service b join (SELECT batch_id from t_batch_service GROUP BY batch_id HAVING COUNT(*)=1)c on b.batch_id=c.batch_id and service_id = &)d WHERE a.batch_name LIKE '%速運券' and a.all_service = 0 and a.status in(0,1,2,3,5) and a.id =d.batch_id; |
分析:查詢方式慢的原因:
參考:https://blog.csdn.net/zuishengmengsi_/article/details/55258826
where a.id = b.id的方式連接表數據,會以笛卡爾積的方式進行連接
join的連接方式中會以on後邊的條件先連接
拓展:cross join也是一種笛卡爾積的方式連接, 即A ×B 這種效率很低