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 去更新了,

也就是 不采用批量更新了,采用 单表更新了。

相关文章
相关标签/搜索