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

关于SQL2008千万级数据量逐行判断的问题
有一个表里保存了1000万的公交车数据量,需要逐行对其中4列的值进行判断。
具体来说:有卡号,日期,时间,线路;判断规则是,同一个卡号,在用90分钟里,线路值不同的话,认为有一次公交换乘。
我的解决思路是,先把这四个列按照卡号,日期,时间排序取出,并存入临时表里。
再定义八个变量,
--定义循环取值变量
declare @l nchar(20)
declare @x nchar(6)
declare @d nchar(8)
declare @sj nchar(6)

declare @ln nchar(20)
declare @xn nchar(6)
declare @dn nchar(8)
declare @sjn nchar(6)
然后用游标逐行取出相邻的两行值,赋值给这八个变量。
接下来依次判断卡号,日期,时间,线路;
单次判断完成后,执行
set @l=@ln
set @x=@xn
set @d=@dn
set @sj=@sjn
再读取下一行记录,并重复判断
用这样的方法能在4分钟里完成
现在发帖求助,是否有更高效的解决方案。
因为,有看到资料说,数据超过1万行就应避免使用游标,改用while来处理
可是我试了while循环,一个晚上都没出结果。
附上SQL代码
--生成临时表
select  * into #b from 
(
select listbh,[dealrq],[dealsj],xlbh  from cpuxfmx2011701720
union all 
select listbh,[dealrq],[dealsj],xlbh  from cpuxfmx2011721731 

AS table_source  

--定义游标
declare test_Cursor cursor scroll for
select listbh,xlbh,[dealrq], dealsj from #b  order by listbh,[dealrq],dealsj
go

open test_Cursor --打开游标

--定义计数器
declare @c int
set @c=0

--定义变量
declare @l nchar(20)
declare @x nchar(6)
declare @d nchar(8)
--3.27增加判断规则,同一天里刷卡时间间隔小于90分钟
declare @sj nchar(6)

declare @ln nchar(20)
declare @xn nchar(6)
declare @dn nchar(8)
declare @sjn nchar(6)

--取第一行的值
fetch FIRST from test_Cursor into @l,@x,@d,@sj

while @@FETCH_STATUS=0
begin

--逐行取值
fetch NEXT from test_Cursor into @ln,@xn,@dn,@sjn

--判断
if @l=@ln
begin
if @x!=@xn
begin
if @d=@dn
begin
--if datediff(minute, convert(datetime, @sj), convert(datetime, @sjn))<=90
--由于dealsj字段里包含不能转换成datetime的值
--采用下述方式判断,并把间隔改成90+40(时间的60进制与数字的10进制差异)=130
if convert(int,(SUBSTRING(@sjn,1,4)))-convert(int,(SUBSTRING(@sj,1,4)))<=130
begin
--累加计数器
set @c=@c+1
end

end

end

end

 set @l=@ln
 set @x=@xn
 set @d=@dn
 set @sj=@sjn 

end

print @c

--关闭游标
close test_Cursor
--销毁游标
deallocate test_Cursor

--销毁临时表
drop table #b 




 

------解决方案--------------------
换CTE试试,1000万用游标能跑出数据证明你的硬件很强大,或者并发很小,不然早挂了。
------解决方案--------------------
卡号,日期,时间,线路
先合并为 card,datetime,line,再用row_number(over card order by datetime)得到按card分组的序号列o

select a.card,a.datetime,b.datetime
from t a
left join t b on a.card=b.card and a.o=b.o-1
where b.datetime-a.datetime<90分钟 and a.line<>b.line

------解决方案--------------------
看下执行计划,应该能分析出慢所在位置。如果没能应用到索引自然会慢。
------解决方案--------------------
引用:
表的结构
COLUMN_NAME DATA_TYPE