通过稍微调整输入数据并略微调整我们如何定义需求,生成预期结果变得非常简单。
首先,我们调整您的date
值,以便唯一变化的是月和年 - 日子都是一样的。我选择这样做,我为每个值添加1天。事实上,这产生了一个月提前的结果在这里并不重要,因为所有的价值都是相似的变化,所以每月的关系保持不变。然后,我们介绍一个数字表 - 在这里,我假设一个小的固定表就足够了。如果它不适合您的需求,您可以轻松地在线查找示例以创建可用于此查询的大型固定数字表。
最后,我们重铸问题陈述。我们不是试图计算几个月,而是问“什么是最小月数,大于等于零,我需要从当前行返回,找到一个非1结果的行?”。因此,我们产生这样的查询:
declare @t table (id int not null,ind int not null,lvl varchar(13) not null,
result int not null,date date not null)
insert into @t(id,ind,lvl,result,date) values
(1 ,1,'a',3,'20170131'), (2 ,1,'a',3,'20170228'), (3 ,1,'a',1,'20170331'),
(4 ,1,'a',1,'20170430'), (5 ,1,'a',1,'20170531'), (6 ,1,'b',1,'20170131'),
(7 ,1,'b',3,'20170228'), (8 ,1,'b',3,'20170331'), (9 ,1,'b',1,'20170430'),
(10,1,'b',1,'20170531'), (11,2,'a',3,'20170131'), (12,2,'a',1,'20170228'),
(13,2,'a',3,'20170331'), (14,2,'a',1,'20170430'), (15,2,'a',3,'20170531')
;With Tweaked as (
select
*,
DATEADD(day,1,date) as dp1d
from
@t
), Numbers(n) as (
select 0 union all select 1 union all select 2 union all select 3 union all select 4
union all
select 5 union all select 6 union all select 7 union all select 8 union all select 9
)
select
id, ind, lvl, result, date,
COALESCE(
(select MIN(n) from Numbers n1
inner join Tweaked t2
on
t2.ind = t1.ind and
t2.lvl = t1.lvl and
t2.dp1d = DATEADD(month,-n,t1.dp1d)
where
t2.result != 1
),
1) as [BadResultRemainsFor%Months]
from
Tweaked t1
的COALESCE
只是有对付边缘的情况下,如您1,b
数据,在没有前一行与非1的结果。
结果:
id ind lvl result date BadResultRemainsFor%Months
----------- ----------- ------------- ----------- ---------- --------------------------
1 1 a 3 2017-01-31 0
2 1 a 3 2017-02-28 0
3 1 a 1 2017-03-31 1
4 1 a 1 2017-04-30 2
5 1 a 1 2017-05-31 3
6 1 b 1 2017-01-31 1
7 1 b 3 2017-02-28 0
8 1 b 3 2017-03-31 0
9 1 b 1 2017-04-30 1
10 1 b 1 2017-05-31 2
11 2 a 3 2017-01-31 0
12 2 a 1 2017-02-28 1
13 2 a 3 2017-03-31 0
14 2 a 1 2017-04-30 1
15 2 a 3 2017-05-31 0
进行调整的另一种方法是使用一个DATEADD
/DATEDIFF
对到对的日期执行 “地板” 操作:
DATEADD(month,DATEDIFF(month,0,date),0) as dp1d
它将所有日期值重置为本月的第一个月,而不是下一个月。这对你来说可能更加“自然”,或者你的原始数据中可能已经有了这样的值。
难道我们保证所有'日期'值都是日期,并且每个月的最后一天都是? –
@Damien_The_Unbeliever是的,它将永远是每个月的最后一天! – Flesym