当前位置: 代码迷 >> Sql Server >> 计算一下产品周期时,当遇到大数据量,就无法计算操作了,请教如何解决
  详细解决方案

计算一下产品周期时,当遇到大数据量,就无法计算操作了,请教如何解决

热度:83   发布时间:2016-04-24 09:19:26.0
计算一下产品周期时,当遇到大数据量,就无法计算操作了,请问怎么解决?
本帖最后由 aken815 于 2015-03-16 14:55:30 编辑
计算一下产品周期时,当遇到大数据量,就无法计算操作了,请问怎么解决?
当使用网友提供的解决方法,一万以内的数据还好解决,当数据量达到五百万以后,就基本没法使用了.

原始数据如下:
卡号 |    产品 |    动作 |    开始日期 |    结束日期
A001 |    A产品 |    开通 |    2014-01-01 |    2014-05-30
A001 |    A产品 |    续约 |    2014-06-01 |    2014-12-31
A001 |    A产品 |    取消 |    2014-06-01 |    2014-12-31
A001 |    A产品 |    重开 |    2014-06-08 |    2015-01-07
A001 |    A产品 |    续约 |    2015-01-08 |    2015-06-07

A002 |    B产品 |    开通 |    2014-01-01 |    2014-05-30
A002 |    B产品 |    续约 |    2014-06-01 |    2014-12-31
A002 |    B产品 |    续约 |    2015-01-01 |    2015-05-30

计算成以下数据:
卡号 |    产品 |    动作 |    开始日期 |    结束日期 |    产品周期
A001 |    A产品 |    开通 |    2014-01-01 |    2014-05-30 |     1
A001 |    A产品 |    续约 |    2014-06-01 |    2014-12-31 |     2
A001 |    A产品 |    取消 |    2014-06-01 |    2014-12-31 |     0
A001 |    A产品 |    重开 |    2014-06-08 |    2015-01-07 |     1
A001 |    A产品 |    续约 |    2015-01-08 |    2015-06-07 |     2

A002 |    B产品 |    开通 |    2014-01-01 |    2014-05-30 |     1
A002 |    B产品 |    续约 |    2014-06-01 |    2014-12-31 |     2
A002 |    B产品 |    续约 |    2015-01-01 |    2015-05-30 |     3

需要计算一下产品周期,计算方法是这样的,开通算1,续约加1,取消归0,取消后产品周期从1重新计算。

下面是网友提供的解决方法:

create table mytable(
卡号 varchar(5) ,产品 varchar(10) ,动作 varchar(10) ,开始日期 varchar(10) ,结束日期 varchar(10)
)
go
insert into mytable values
('A001','A产品','开通','2014-01-01','2014-05-30'),
('A001','A产品','续约','2014-06-01','2014-12-31'),
('A001','A产品','取消','2014-06-01','2014-12-31'),
('A001','A产品','重开','2014-06-08','2015-01-07'),
('A001','A产品','续约','2015-01-08','2015-06-07'),
('A002','B产品','开通','2014-01-01','2014-05-30'),
('A002','B产品','续约','2014-06-01','2014-12-31'),
('A002','B产品','续约','2015-01-01','2015-05-30')
go
with myrn as (
select * ,ROW_NUMBER() over(partition by 卡号 order by 卡号) as rn from mytable
) , 
mt as (
select * , 1 as 产品周期 from myrn where rn = 1 
union all
select myrn.* , case when myrn.动作 = '续约' then mt.产品周期 + 1 
                     when myrn.动作 = '取消' then 0 
                     when myrn.动作 = '重开' then 1 
                end 
from mt , myrn where myrn.rn = mt.rn + 1 and mt.卡号 = myrn.卡号
)
select * from mt order by 卡号 , rn 
go
drop table mytable 
go

(8 行受影响)
卡号    产品     动作       开始日期   结束日期   rn  产品周期
----- ---------- ---------- ---------- ---------- --- -----------
A001  A产品      开通       2014-01-01 2014-05-30 1   1
A001  A产品      续约       2014-06-01 2014-12-31 2   2
A001  A产品      取消       2014-06-01 2014-12-31 3   0
A001  A产品      重开       2014-06-08 2015-01-07 4   1
A001  A产品      续约       2015-01-08 2015-06-07 5   2
A002  B产品      开通       2014-01-01 2014-05-30 1   1
A002  B产品      续约       2014-06-01 2014-12-31 2   2
A002  B产品      续约       2015-01-01 2015-05-30 3   3

(8 行受影响)


我自己使用上面的语句,数据量选择一万或以上(我总数据量有五百五十万左右),就无法计算出来并插入到临时表了,等了半个钟或更长时间,一点反应都没有....

with myrn as (
select 编号,卡号,动作 ,ROW_NUMBER() over(partition by 卡号 order by 卡号) as rn 
from 业务表 
), 
mt as (
select 1 as 产品周期,* from myrn where rn = 1 
union all
select case when myrn.动作 = '续约' then mt.iActCount2 + 1 
                     when myrn.动作 = '取消' then 0
                     when myrn.动作 = '重开' then 1
 when myrn.动作 = '新开' then 1
                end, myrn.*
from mt , myrn where myrn.rn = mt.rn + 1 and mt.卡号 = myrn.卡号
)

INSERT INTO 业务表临时表
(编号, 卡号, 产品周期, 动作
)
SELECT 编号, 卡号, 产品周期, 动作
FROM mt b
------解决思路----------------------
表数据太大,可以插入到临时表,然后 临时表关联字段加索引看看
------解决思路----------------------

將上面的sql的優化一下,將繁體改為簡體,試一下是否OK。

with cte as
(
select *,ROW_NUMBER() over(partition by 卡號,產品 order by 開始日期) as rn,1 as 生產週期
from mytable
),
cte1 as 
(
select * from cte where rn=1
union all
select aaa.卡號,aaa.產品,aaa.動作,aaa.開始日期,aaa.结束日期,aaa.rn,
case when  aaa.動作 = '續約' then bbb.生產週期+ 1 
  when aaa.動作 = '取消' then 0
  when aaa.動作 = '銷約' then bbb.生產週期 - 1
  when aaa.動作 = '停卡' then 0
  when aaa.動作 = '重授' then bbb.生產週期
  else aaa.生產週期
  end  as score
from cte as aaa,cte1 as bbb where aaa.卡號=bbb.卡號 and aaa.產品=bbb.產品 and aaa.rn=bbb.rn+1
)
select * from cte1 order by 卡號,產品,rn

------解决思路----------------------
上面的CTE是递归的,数据量太大的话,恐怕执行效率不会高。建议还是写存储过程吧,按卡号或者产品分批将数据读取到临时表中,计算出产品周期,再更新到原表,最后一起输出。
  相关解决方案