The problem is that when an area is merged and its code is reused, you have that information, but when an area is merged and its code is deprecated, you don't have it. In other words, you don't have the information that an area is deprecated.
Now, I see two solutions. First, keep the schemas as is and whenever an area is deprecated, add a new row as it was a new area and just states it is deprecated, e.g.
INSERT INTO myTable(code, area, change_date)
VALUES(86001, 'deprecated', '2015-01-01')
So in your query it will show as 'deprecated'
or you filter it out.
A second, and possible best option, is to have a new column that states when (and if) an area was deprecated:
ALTER TABLE myTable ADD deprecated DATE;
UPDATE myTable SET deprecated = '2015-01-01' WHERE gid = 1;
So, on your query you can simple add the filter:
(deprecated IS NULL OR deprecated >= '2016-01-01')
The full code:
SELECT DISTINCT ON (code) code, area, change_date
FROM myTable
WHERE change_date < '2016-01-01'
AND (deprecated IS NULL OR deprecated >= '2016-01-01')
ORDER BY code, change_date DESC;
As another option for non-deprecated areas, you can set them as 'infinity'
instead of NULL
, so the query does not need the deprecated IS NULL
condition, as 'infinity'
will always be higher or equal than any other non-null value.
Best Answer
The 2*14+3 in the CTE is a safe upper limit and can be improved.