Sql server SQL server:如何计算中每个观察值的最大持续更改
我用的是SQLServer2012。我想计算每个obs的最大连续更改数。像这样的桌子Sql server SQL server:如何计算中每个观察值的最大持续更改,sql-server,cursor,window,fetch,aggregate-functions,Sql Server,Cursor,Window,Fetch,Aggregate Functions,我用的是SQLServer2012。我想计算每个obs的最大连续更改数。像这样的桌子 snapshot\u date customer\u id Number Max\u consercutive\u increase\u作为每行的\u 一月十四日1234200 二月十四日12342 15 1 三月十四日12342452 四月十四日12342 02 5月14日12342 15 2 六月十四日12342452 七月十四日12342753 八月十四日12342 105 4 2014年9月12342
snapshot\u date customer\u id Number Max\u consercutive\u increase\u作为每行的\u
一月十四日1234200
二月十四日12342 15 1
三月十四日12342452
四月十四日12342 02
5月14日12342 15 2
六月十四日12342452
七月十四日12342753
八月十四日12342 105 4
2014年9月12342 135 5
10月14日12342 04
11月14日12342 03
十二月十四日12342 02
一月十五日12342 01
二月十五日1234200
三月十五日1234200
4月15日12342 0 0
这应该适合您:
-- Create test data
declare @t table(snapshot_date date,customer_id int,Number int);
insert into @t values ('20140101',12342, 0 ),('20140201',12342, 15 ),('20140301',12342, 45 ),('20140401',12342, 0 ),('20140501',12342, 15 ),('20140601',12342, 45 ),('20140701',12342, 75 ),('20140801',12342, 105 ),('20140901',12342, 135 ),('20141001',12342, 0 ),('20141101',12342, 0 ),('20141201',12342, 0 ),('20150101',12342, 0 ),('20150201',12342, 0 ),('20150301',12342, 0 ),('20150401',12342, 0 );
with d as -- Add a row number to the dataset
(
select snapshot_date
,customer_id
,Number
,row_number() over (order by snapshot_date) as rn
from @t
)
,c as -- Use a recursive CTE to loop through the dataset and check for increases
(
select snapshot_date
,customer_id
,Number
,rn
,0 as ConsecutiveIncreases
from d
where rn = 1
union all
select t.snapshot_date
,t.customer_id
,t.Number
,t.rn
,case when t.Number > c.Number then c.ConsecutiveIncreases + 1 else 0 end
from d as t
join c
on t.rn = c.rn+1
)
-- Take the MAX consecutive increase where the current row is also an increase,
-- unless the row is not an increase, then subtract the number of non-increases
-- from the MAX consecutive increase to find the number of increases within the last 6 rows.
-- If less than 6 rows to use, just take the MAX increase.
select c.snapshot_date
,c.customer_id
,c.Number
,case when isnull(sum(c2.ConsecutiveIncreases),0) = 0
then 0
when count(c2.ConsecutiveIncreases) < 6
then max(c2.ConsecutiveIncreases)
else max(c2.ConsecutiveIncreases) - case when c.ConsecutiveIncreases = 0
then sum(case when c2.ConsecutiveIncreases = 0
then 1
else 0
end
)
else 0
end
end as MaxConsecutiveIncreases
from c
left join c as c2
on c2.rn between c.rn-5 and c.rn
group by c.snapshot_date
,c.customer_id
,c.Number
,c.ConsecutiveIncreases
order by 1
你能把你的脚本发布到现在吗?你是怎么尝试的。我曾经尝试过使用游标和fetch-relative,比如:fetch-relative-5 from Test1cursor to。。。从Test1cursor获取相对-5到。。。谢谢你的回答。但我认为在快照日期2014-04-01,MaxConcertiveIncrease应该是2,因为前面06行中的“number”列增加了02倍。请分享更多关于你的逻辑,因为这对我来说是新的,还有一件事@iamdave。我的表大约有1.000.000行,因此如果我使用递归cte,会出现问题,因为临时数据非常大?@trato更新了我的脚本。由于您希望这样做,我还无法找到一种有效的基于集合的方式来实现这一点,因此它总是很慢。
+---------------+-------------+--------+-------------------------+
| snapshot_date | customer_id | Number | MaxConsecutiveIncreases |
+---------------+-------------+--------+-------------------------+
| 2014-01-01 | 12342 | 0 | 0 |
| 2014-02-01 | 12342 | 15 | 1 |
| 2014-03-01 | 12342 | 45 | 2 |
| 2014-04-01 | 12342 | 0 | 2 |
| 2014-05-01 | 12342 | 15 | 2 |
| 2014-06-01 | 12342 | 45 | 2 |
| 2014-07-01 | 12342 | 75 | 3 |
| 2014-08-01 | 12342 | 105 | 4 |
| 2014-09-01 | 12342 | 135 | 5 |
| 2014-10-01 | 12342 | 0 | 4 |
| 2014-11-01 | 12342 | 0 | 3 |
| 2014-12-01 | 12342 | 0 | 2 |
| 2015-01-01 | 12342 | 0 | 1 |
| 2015-02-01 | 12342 | 0 | 0 |
| 2015-03-01 | 12342 | 0 | 0 |
| 2015-04-01 | 12342 | 0 | 0 |
+---------------+-------------+--------+-------------------------+