使用 mysql 就不太强,并且写的复杂SQL可能是 select 查询语句,最怕复杂的 update 语句了。mysql
因此在这里总结一下sql
有一张订单明细表,我须要 更新 明细表里面的 金额和重量, 这个 更新的依据是 根据 订单明细表里面的 某些数据的 来进行 算出来 重量或者金额 来进行更新的。函数
固然 这个订单明细表 须要根据 订单主表 来进行查询出来。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
参考地址: 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 去更新了,
也就是 不采用批量更新了,采用 单表更新了。