You can do (TSQL for MS SQL Server, other DBMS syntax may vary):
select YEAR(salesdate),count(*) as c
from test_dates
where canceldate is null
group by YEAR(salesdate)
This will group by the year of the salesdate and ignore those where canceldate is set. This will only give customers grouped by year of first sale, so to get the active customers in all years from 2011 to 2016 here is a different solution. It creates a "years of interest" table and joins this to the dates/customers table using a join condition of "BETWEEN ... and ...", which is TSQL shorthand for a<=b<=c
.
edit:
CREATE TABLE #dates (
[cn] [int] NOT NULL,
[sal] [date] NOT NULL,
[can] [date] NULL
)
insert into #dates
VALUES
(1,try_parse('2016-01-01' as date),NULL),
(2,try_parse('2016-01-05' as date),NULL),
(3,try_parse('2015-02-02' as date),try_parse('2015-02-05' as date)),
(4,try_parse('2011-04-09' as date),NULL),
(5,try_parse('2013-01-10' as date),try_parse('2015-01-10' as date))
create table #years (y int NOT NULL)
insert into #years VALUES (2011),(2012),(2013),(2014),(2015),(2016)
select d.*, #years.y
into #cust_all_years
from #dates as d
inner join #years on #years.y BETWEEN YEAR(d.sal) and ISNULL(YEAR(d.can),9999)
The ISNULL corrects for the cases where the cancel date is not set.
select y,count(*) as c from #cust_all_years
group by y
or Datepart(year, CancelDate) = NULL
. Do not ever compareNULL
to something using=
. You have to useIS NULL
orIS NOT NULL