一直写select语句, 很少写复杂的update语句,
最近我想批量更新一个表,要求是更新每条数据的a字段,具体更新的值是这条数据的id字段在b字段中出现的次数.简单的理解为下图:
表: abc
把count字段更新为其id在f_id中出现的次数,update完成后应该是:
表:abc
即id为1的count值是2,因为1在f_id中出现了2次; id为2的count值是3,因为2在f_id中出现了3次;
我刚开始的解决思路是这样的:
update abc a1 set count = (
select co from (
select count(*) from abc a2 where a1.id = a2.f_id
) aa
)
但是它会报错, 说不认识a1.id :
Unknown column 'a1.id' in 'where clause'
看他的错误信息意思好像是a1.id 不能出现在where从句里,那我在where之前去用好不好呢?
然后我就这样去写:
update abc a1 set count = (
select co from (
select sum(case a1.id when a2.f_id then 1 else 0 end) co from abc a2
) aa
)
我还是太天真啊... 还是报错: Unknown column 'a1.id' in 'field list'
然后我问了朋友才知道, 我们要用select查询造的虚拟表当做查询源的时候, 这个select语句是完全独立的, 不和他以外的SQL相通,所以就不认识定义的别名a1了.
好吧,明确知道这条路走不通了之后,我陷入深深的绝望,然后搜索相关批量更新的帖子,发现有人用这种方法:
update 表1 a1 inner join (select 字段1,字段2 from 表1 where 条件) a2 on 条件
set a1.字段1 = a2.字段2
哇,这个思路厉害了啊 先造出来一个虚拟表,然后通过更新虚拟表的方式去实现具体的更新;
然后我就这样去写:
update abc a inner join (select f_id, count(*) co from abc group by f_id) b on a.id = b.f_id
set a.count = b.co
内连接出来的虚拟表是:
abc表:
a.id a.f_id a.count
1 0 0
2 1 0
3 1 0
4 2 0
6 2 0
7 2 0
+
查询结果:
b.f_id b.co
0 1
1 2
2 3
=
虚拟表:
a.id a.f_id a.count b.f_id b.co
1 0 0 1 2
2 1 0 2 3
然后set a.count = b.co 就ok了
虽然是操作的虚拟表,但是能影响到具体的实体表啊!!
不知道是不是我太孤落寡闻了... 对于这种操作真的是想不到啊.
好了,再看下这个sql:
update
abc a
inner join
(select f_id, count(*) as co from abc group by f_id) b
on
a.id = b.f_id
set
a.count = b.co
我们也换一下用左联接
(更新的是虚拟表左边的字段,左联接可以保证虚拟表左边的字段都有实体表字段相对应,不至于set的对象是个null,set的值是个null不怕,但是把一个值set给null就有问题了):
update
abc a
left join
(select f_id, count(*) as co from abc group by f_id) b
on
a.id = b.f_id
set
a.count = ifnull(b.co,0) /*左联接有可能右边没有对应的值, 当没有时设置为0)*/
记下来,加强一下印象,也希望能帮助到新手朋友;