日期:2014-05-17  浏览次数:20885 次

一个改写rownum的问题
我有2个表,一个是Data, 里面有personId, name, date等字段,这个表比较小,最多几千条记录,另外一个是person表,里面有id, name等,这个表很大,有上千万条记录,并且有少量id重复,其实就是一个身份证号对应2个名字(因为有人改过名字),现在有个需求是用person表里的name来更新Data表里的名字,Oracle的语句大概如下:
update Data set name = (select name from person where person.id = personId and rownum = 1) where date = '2013-01-23'
这样就是如果person里同一个id有2个名字那就用第一条记录的name来更新。这个没有问题。现在我们有需求把他改成别的数据库语句来写,里面没有rownum这个关键字,我尝试用
update Data set name = (select top 1 name from person where person.id = Data.id ) where date = '2013-01-23'
来写,但是语法错误,说是相关子查询里不能有排序,所以现在想到的是用inner join:
update data set name = pname from data inner join (select min(name), id from person group by id) b on b.id = personId where date = '2013-01-23'
这个可以工作,但是很慢,因为group by的时候有上千万个分组,但实际要更新的数据只有几十条。所以不知道各位高手有没有这方面的经验,有什么简单的办法可以实现这个功能?谢谢!
一次只能给100分,如果解决可以另开贴给分,现在就卡在这里了。。。

------解决方案--------------------
SQL> update data set name = (select min(name) from person where data.personid = person.id) where exists(select 1 from person where data.personid = person.id)  and date = '2013-01-23'

------解决方案--------------------
在person的id列建个索引看看
------解决方案--------------------
先将重复的记录 过滤后跑到临时表

再跟临时表 去更新
------解决方案--------------------
方法1
前提:
不是一定要一句SQL實現
person.personid上建立索引

1。對Data數據loop,
2。抽出Data.personId
3。根據Data.personId,從person中抽person.name
   這個時候可以用group(推薦) 或者top1來取得name 
4。用person.name 更新Data.name

思路:由於單個的輕負荷的檢索性能很高,而且便於優化
所以即使是loop,次數有千,從person中抽person.name
的sql可以優化出很高的性能

方法2:
必須一句sql,可以非同期
利用實體view,保存和Data有關係的數據,更新的時候
和實體view作join