mysql 執行復雜 update 更新, 關聯表 以及 使用sum()等函數

使用 mysql 就不太強,並且寫的複雜SQL可能是 select 查詢語句,最怕複雜的 update 語句了。mysql

因此在這裏總結一下sql

  1.  關聯須要更新的表或者根據 須要更新表,來執行更新

 有一張訂單明細表,我須要 更新 明細表裏面的 金額和重量, 這個 更新的依據是 根據 訂單明細表裏面的  某些數據的 來進行 算出來 重量或者金額 來進行更新的。函數

固然 這個訂單明細表 須要根據 訂單主表 來進行查詢出來。spa

 

首先 第一步 我寫出來的SQL ,看起來也不算複雜.net

UPDATE gwqmshop_process_order_item set total_weight=1*count * (
	 SELECT units.unitWeight from (
	SELECT isrc.total_weight/isrc.count as unitWeight from	gwqmshop_process_order_item as isrc 
   where src_order_item_id=isrc.id 	
	) as units
	),
 total_amount=total_weight*price
 where id in (
	SELECT item.id from 
  (
	SELECT it.id  from  gwqmshop_process_order_item as it
 where 
it.disabled=0 
	and it.order_id in (
	SELECT o.id from gwqmshop_process_order o  where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00'
	) 
  ) item
);

 

更新的時候 where 語句必須 這樣的寫法, 調試

不然 mysql 就會報錯,由於 mysql 是不能 經過 查詢 自身而後來進行 更新的。code

報錯內容:server

MYSQL之You can't specify target table for update in FROM clause

 

參考地址: https://blog.csdn.net/z_youarethebest/article/details/53785487blog

 

上面的剛纔我寫的SQL語句, 是沒有報錯, 但是 執行更新以後, 更新的結果都 是 被更新爲 null 了。ci

我這裏是 mysql 5.6 不知道是否是 mysql的bug , 即沒有報錯,又被更新爲 null 了。。。

緣由是 由於  where src_order_item_id=isrc.id      這個語句, 在 mysql 中 是 獲取 不到  

訂單明細表 裏面的 src_order_item_id  這個字段內容的。

若是咱們改成 :

where isrc.id=gwqmshop_process_order_item.src_order_item_id

mysql 就會報錯了, 報錯是由於 找不到  gwqmshop_process_order_item 表。

其實無論是 update 語句,仍是 select 語句,  字段 經過  查詢其餘表,可是又須要更加當前查詢的表的內容取管理的話,都是會報錯的。

由於 最外層的表的內容傳不去裏面的 臨時表的。

例子 :

SELECT  i.id ,i.src_order_item_id,i.total_amount,i.total_weight,i.count * ( 
	SELECT isrc.total_weight/isrc.count
	from gwqmshop_process_order_item isrc where isrc.id =i.src_order_item_id
) 
 from gwqmshop_process_order_item i 
where i.disabled=0 
	and i.order_id in (
	SELECT o.id from gwqmshop_process_order o  where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00'
	) ;


上面的語句確定是沒有問題的,若是改動一下就有問題了

 SELECT  i.id ,i.src_order_item_id,i.total_amount,i.total_weight,i.count * (
  SELECT units.unitWeight from  
	(SELECT isrc.total_weight/isrc.count  as unitWeight
	from gwqmshop_process_order_item isrc where isrc.id =i.src_order_item_id
	)  as units
) 
 from gwqmshop_process_order_item i 
where i.disabled=0 
	and i.order_id in (
	SELECT o.id from gwqmshop_process_order o  where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00'
	) ;


而後就會報錯 :
Unknown column 'i.src_order_item_id' in 'where clause'



那爲何更新的時候不能使用第一種的方式呢?

	UPDATE gwqmshop_process_order_item set gwqmshop_process_order_item.total_weight=1*gwqmshop_process_order_item.count * (
	
	SELECT isrc.total_weight/isrc.count as unitWeight from	gwqmshop_process_order_item as isrc 
   where isrc.id=gwqmshop_process_order_item.src_order_item_id 	
	
	),
 gwqmshop_process_order_item.total_amount=gwqmshop_process_order_item.total_weight*gwqmshop_process_order_item.price
 where gwqmshop_process_order_item.id in (
	SELECT item.id from 
  (
	SELECT it.id  from  gwqmshop_process_order_item as it
 where 
it.disabled=0 
	and it.order_id in (
	SELECT o.id from gwqmshop_process_order o  where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00'
	) 
  ) item
);

上面的更新語句就會爆錯,仍是以前的錯誤,不能經過查詢 自身來更新 
報錯:
 You can't specify target table 'gwqmshop_process_order_item' for update in FROM clause

 

 

上面的辦法都不能成功,而後我也亂寫了一通,都搞不定,,,都本身的錯,寫代碼寫出BUG了,必須執行更新語句,,,本身的坑,本身填。。。

網上亂看,而後 本身亂寫,亂調試:

最終解決update SQL語句:

UPDATE gwqmshop_process_order_item,gwqmshop_process_order_item units

 set gwqmshop_process_order_item.total_weight=1*gwqmshop_process_order_item.count * (units.total_weight/units.count),
 gwqmshop_process_order_item.total_amount=gwqmshop_process_order_item.total_weight*gwqmshop_process_order_item.price
 where gwqmshop_process_order_item.id in (
	SELECT item.id from 
  (
	SELECT it.id  from  gwqmshop_process_order_item as it
 where 
it.disabled=0 
	and it.order_id in (
	SELECT o.id from gwqmshop_process_order o  where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00'
	) 
  ) item
) and units.id = gwqmshop_process_order_item.src_order_item_id;

 

原來只須要  update 的是, 再 來一個自身表 便可。

由於以前 沒有這樣想是由於 感受多是 會 報錯,由於查詢了自身表又更新了。。。

- You can't specify target table 'gwqmshop_process_order_item' for update in FROM clause

由於沒有報錯,能夠成功是由於 mysql 的 底層區分開了吧。

 gwqmshop_process_order_item,gwqmshop_process_order_item units 可能就是兩個 不會產生關聯的表吧。

 

 

2.   update 執行,使用SUM() 函數

 

訂單明細表,已經更新了 重量和金額了,那麼 還須要 更新 訂單主表啊,由於訂單主表也有 總的 重量和金額。。。

看起來挺簡單,更加明細表求和,更加便可。

估計你們通常會這樣寫:

## 再更新訂單的 總理論重量和總理論價格

update gwqmshop_process_order 
set total_weight =(
sum(
SELECT it1.total_weight  from  gwqmshop_process_order_item as it1
where it1.order_id=id and it1.disabled=0
)
),
set total_price=(
sum(
SELECT it2.total_amount  from  gwqmshop_process_order_item as it2
where it2.order_id=id and it2.disabled=0
)
)
where id in 
(
 SELECT mo.id from (
SELECT o.id as id from gwqmshop_process_order o  where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00'
	) as mo
);

 

可是 執行以後 報錯:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT it1.total_weight  from  gwqmshop_process_order_item as it1
where it1.ord' at line 4

語法錯誤,什麼鬼,,,沒有錯誤啊。反正就是不行。

 

看不問題,我試着簡化一下SQL:

update gwqmshop_process_order ,
gwqmshop_process_order_item  it1 
set gwqmshop_process_order.total_weight =sum(it1.total_weight)
where gwqmshop_process_order.id in 
(
 SELECT mo.id from (
SELECT o.id as id from gwqmshop_process_order o  where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00'
	) as mo
)
and it1.order_id=gwqmshop_process_order.id and it1.disabled=0
;

 

就爆出來 :

 Invalid use of group function

看起來 感受是 使用不了 sum 函數啊。。。

想一想也是,  sum 函數也算分組函數吧,分組求和的。。。

咱們通常使用 sum 函數都是 在 select 語句中的,  沒有這樣直接使用的。。。

因此要改一下, 隨便試了一下,沒成功, 去百度看看

能夠參考: https://stackoverflow.com/questions/653826/update-with-sum-in-mysql

UPDATE Table_NAme SET PAR= summedValue
FROM   TAble_NAME t
JOIN (
  SELECT ID, SUM(S_val) as summedvalue 
  FROM TABLE_NAME GROUP BY ID
  ) s on t.ID = s.ID

 

這樣子 感受 好像行的通, 但是怎麼使用MYSQL 寫出來?

 

試着用join 關聯:

update gwqmshop_process_order ,
 inner join 
(
SELECT gwqmshop_process_order_item.order_id as order_id ,sum(gwqmshop_process_order_item.total_weight) as sumweight  from gwqmshop_process_order_item
where gwqmshop_process_order_item.disabled=0 
) as itsum on itsum.order_id=gwqmshop_process_order.id

set gwqmshop_process_order.total_weight =itsum.sumweight 
where gwqmshop_process_order.id in 
(
 SELECT mo.id from (
SELECT o.id as id from gwqmshop_process_order o  where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00'
	) as mo
)
;


報錯。。。
check the manual that corresponds to your MySQL server version for the right syntax to use near 'inner join 
(
SELECT gwqmshop_process_order_item.order_id as order_id ,sum(gwq' at line 2




試試下面的:

update gwqmshop_process_order ,
(
SELECT gwqmshop_process_order_item.order_id as order_id ,sum(gwqmshop_process_order_item.total_weight) as sumweight  from gwqmshop_process_order_item
 GROUP BY  gwqmshop_process_order_item.order_id
) as itsum
left  JOIN itsum itsum1 on itsum1.order_id=gwqmshop_process_order.id
set gwqmshop_process_order.total_weight =itsum1.sumweight
where gwqmshop_process_order.id in 
(
 SELECT mo.id from (
SELECT o.id as id from gwqmshop_process_order o  where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00'
	) as mo
)

;




 Table 'yxshop.itsum' doesn't exist  報錯,仍是不行。

 

 

最終解決辦法:

因而使用下面的:


update gwqmshop_process_order ,
 (
SELECT gwqmshop_process_order_item.order_id as order_id ,sum(gwqmshop_process_order_item.total_weight) as sumweight,
 sum(gwqmshop_process_order_item.total_amount) as sumamount
  from gwqmshop_process_order_item
 GROUP BY  gwqmshop_process_order_item.order_id
) as itsum
set gwqmshop_process_order.total_weight =itsum.sumweight,
gwqmshop_process_order.total_price=itsum.sumamount

where gwqmshop_process_order.id in 
(
 SELECT mo.id from (
SELECT o.id as id from gwqmshop_process_order o  where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00'
	) as mo
)
and  itsum.order_id=gwqmshop_process_order.id
;

 

上面的SQL在 mysql 5.6 下面沒有問題,

 

可是在 mysql5.7 下面就報錯:

You can't specify target table 'gwqmshop_process_order' for update in FROM clause
 

也是奇怪,還好生產環境使用 mysql5.6  

 

mysql 5.7 的報錯,不知道是否是BUG,否則爲何mysql5.6 沒事?

並且從報錯的角度來看,,,不知道怎麼會出現這樣錯誤??

 

我也不還知道怎麼辦了

 

由於 


update gwqmshop_process_order
set total_price=total_price

where 

id in 
(
 SELECT mo.id from (
SELECT o.id as id from gwqmshop_process_order o  where o.disabled=0 and o.data_type=3 and o.createtime>'2018-05-26 22:00:00'
    ) as mo
)

;
這樣子在 mysql 5.7 下面行不通, 

有最笨的方式就是 拼出來 執行的全部的 update SQL, 

先把 全部的訂單ID查詢出來,而後根據訂單id 去更新了,

也就是 不採用批量更新了,採用 單表更新了。

相關文章
相關標籤/搜索