GAPS and ISLANDS
Here is the solution that uses the principle of search for gaps and Islands.
-- código #1 v4
with
C as (
SELECT Pessoa_Id, Ano, Valor,
ilha= (Ano - DENSE_RANK() OVER(partition by Pessoa_Id order by Ano))
from Doação
where Valor is not null
)
SELECT Pessoa_Id,
count(*) as Ininterrupto,
min(Valor) as [Menor valor],
max(Valor) as [Maior valor],
avg(Valor) as Média,
sum(Valor) as Total
from C
group by Pessoa_Id, ilha
having max(Ano) = 2017;
Adapted code of the article Solving Gaps and Islands with Enhanced Window Functions. If the SQL Server version is 2012, or newer, you can use the new window functions, as stated in the article.
CTE RECURSIVE
Here is another solution, based on CTE recursive that starts reading by all lines of the year 2017 that have value informed and continues reading in sequence inverse order, until find no value (NULL) or break in the column of year.
-- código #2
with bloco2017 as (
SELECT Pessoa_id, Ano, Valor
from Doação
where Ano = 2017
and Valor is not null
union all
SELECT T1.Pessoa_id, T1.Ano, T1.Valor
from Doação as T1
inner join bloco2017 as T2 on T1.Pessoa_Id = T2.Pessoa_Id
and T1.Ano = (T2.Ano -1)
where T1.Valor is not null
)
SELECT Pessoa_Id,
count(*) as Ininterrupto,
min(Valor) as [Menor valor],
max(Valor) as [Maior valor],
avg(Valor) as Média,
sum(Valor) as Total
from bloco2017
group by Pessoa_Id;
For testing:
-- código #3 v2
CREATE TABLE Doação (
Pessoa_id int,
Valor money,
Ano smallint
);
INSERT into Doação values
(1212, 80, 2009),
(1212, 90, 2010),
(1212, 100, 2011),
(1212, NULL, 2012),
(1212, 120, 2013),
(1212, NULL, 2014),
(1212, NULL, 2015),
(1212, 150, 2016),
(1212, 160, 2017);
INSERT into Doação values
(1213, 300, 2009),
(1213, 200, 2010),
(1213, 100, 2011),
(1213, 50, 2012),
(1213, NULL, 2013),
(1213, 20, 2014),
(1213, 800, 2016),
(1213, 100, 2017);
For the person 1213 purposely does not contain information about the year 2015, to demonstrate that the code also deals with breaking in sequence (i.e., absence of line).
I’m using version 11
– EmanuelF
I refer to the version of SQL Server: 2017, 2016, 2014, 2012 etc. If you do not know, no problem.
– José Diz
I was wondering, I’m using the SS 2016
– EmanuelF