读书人

求较好的算法,该如何解决

发布时间: 2012-03-09 21:42:54 作者: rapoo

求较好的算法
现在有这样一张表

代码(varchar(4)) 时间(datetime) 内容(varchar(200))
0001 2006-12-08 gegegw
0001 2006-11-07 gewhh4
0001 2006-10-01 hhhfgweg
0001 2006-08-05 gewgg
......
0002 2006-11-01 g4h43h
0002 2006-09-08 gg4h3h
0002 2006-08-02 gwgg4
......
0003 2006-06-07 grhrehrehhreh
0003 2006-05-05 grhrhreh
0003 2005-05-01 ghsbre
......
0005 2006-11-01 ghsbre
......
说明
(以上为同一张表,大约20万条记录,更新是按时间插入新的记录,每月一个代码只有一条记录。
为了方便各位理解我是按代码、时间排了序。
不用考虑内容列)

现在想实现下面一张表
代码(varchar(4)) 连续次数(int) 时间(datetime)
0001 3 2006-12-08
0002 12006-11-01
0003 22006-06-07
0004 0 null
0005 1 2006-11-01

其中
代码列 其实是从另外一张代码表,不过这里可以理解为源表的代码,只是在目的表中可能会出现如0004的情况。
时间列 是指 该代码在距离指定日期(如2007-01-01)最近一次在表中出现的时间。
连续次数列 是指 该代码距离指定日期(如2007-01-01)最近一次出现的,月份连续值。
(即,计算月份连续值时,不用考虑时间中的‘日’。当月份出现中断时,哪怕只有一个月,也只算中断月份以后的月数)


我自己到了一个算法,要分两次循环
第一次循环,先查出其中一家企业的出现的最后日期,再拿月份减一循环到中断月出现,返回循环次数
第二次循环,将代码表中的代码逐个用第一个循环运行

问题在于第二次循环。
代码表中一共有2万多个代码,运行起来,就算不死机,估计也需要很长时间能执行完
而系统要求,目的表的生成不能超过20分钟

不知道各位高手有没有更好的算法?




[解决办法]
SELECT M.代码,(CASE WHEN COUNT(N.时间)=0 THEN 1 ELSE COUNT(N.时间)),M.时间
(select 代码,max(时间) as 时间 FROM 表 GROUP BY 代码) M LEFT JOIN
(select A.代码,A.时间 from 表 A LEFT JOIN 表 B
ON A.代码=B.代码 AND B.时间=(SELECT MAX(时间) FROM 表 WHERE 代码=A.代码 AND 时间 <A.时间 AND DATEDIFF(MONTH,时间,A.时间) <=1)


WHERE B.代码 NOT IS NULL) N ON M.代码=N.代码
GROUP BY M.代码,M.时间
[解决办法]
declare @a table(代码 varchar(4),时间 datetime,内容 varchar(200))
insert @a select '0001 ', '2006-12-08 ', 'gegegw '
union all select '0001 ', '2006-11-07 ', 'gewhh4 '
union all select '0001 ', '2006-10-01 ', 'hhhfgweg '
union all select '0001 ', '2006-08-05 ', 'gewgg '
union all select '0002 ', '2006-11-01 ', 'g4h43h '
union all select '0002 ', '2006-09-08 ', 'gg4h3h '
union all select '0002 ', '2006-08-02 ', 'gwgg4 '
union all select '0003 ', '2006-06-07 ', 'grhrehrehhreh '
union all select '0003 ', '2006-05-05 ', 'grhrhreh '
union all select '0003 ', '2005-05-01 ', 'ghsbre '
union all select '0005 ', '2006-11-01 ', 'ghsbre '

declare @b table(id int identity(1,1),代码 varchar(4))
insert @b select '0001 '
insert @b select '0002 '
insert @b select '0003 '
insert @b select '0004 '
insert @b select '0005 '

select b.代码,isnull(连续次数,0),convert(varchar(10),时间,120) from (
select 代码,连续次数=count(1)+1,时间=(select max(时间) from @a where 代码=a.代码) from @a a where exists(select 1 from @a where 代码=a.代码 and datediff(mm,时间,a.时间)=1 ) group by 代码
union all
select 代码,连续次数=1,时间=min(时间) from @a group by 代码 having count(1)=1
) a Right Join @b b On a.代码=b.代码

读书人网 >SQL Server

热点推荐