The Norwegian identification number is more complicated than you suggest, as touched on in this question. You can adapt the answer from that; using a CTE to generate the same dummy data on that answer plus a couple of D numbers (and without the unhelpful future-dated value):
with t42 (ssn) as (
select '12104900000' from dual
union all select '12105099999' from dual
union all select '01010000001' from dual
union all select '02029949902' from dual
union all select '03035450003' from dual
union all select '04049974904' from dual
union all select '05050050005' from dual
union all select '07074090007' from dual
union all select '08089999908' from dual
union all select '01121799908' from dual
union all select '48089999908' from dual
union all select '52104900000' from dual
)
select ssn
from t42
where months_between(trunc(sysdate), to_date(
case
when to_number(substr(ssn, 1, 2)) > 31
then to_char(to_number(substr(ssn, 1, 2)) - 40, 'FM00')
else substr(ssn, 1, 2)
end
|| substr(ssn, 3, 2)
|| case
when to_number(substr(ssn, 7, 3)) between 0 and 499
and to_number(substr(ssn, 5, 2)) between 0 and 99 then '19'
when to_number(substr(ssn, 7, 3)) between 500 and 749
and to_number(substr(ssn, 5, 2)) between 54 and 99 then '18'
when to_number(substr(ssn, 7, 3)) between 500 and 999
and to_number(substr(ssn, 5, 2)) between 0 and 39 then '20'
when to_number(substr(ssn, 7, 3)) between 900 and 999
and to_number(substr(ssn, 5, 2)) between 40 and 99 then '19'
end
|| substr(ssn, 5, 2), 'DDMMYYYY')
) < 360;
which gets five of the twelve dummy values back:
SSN
-----------
02029949902
05050050005
08089999908
01121799908
48089999908
Or with the converted dates and ages:
with ...
select ssn, to_char(dob, 'YYYY-MM-DD') as dob,
trunc(months_between(trunc(sysdate), dob)) as age_in_months,
trunc(months_between(trunc(sysdate), dob)/12) as age_in_years
from (
select ssn,
to_date(
case
when to_number(substr(ssn, 1, 2)) > 31
then to_char(to_number(substr(ssn, 1, 2)) - 40, 'FM00')
else substr(ssn, 1, 2)
end
|| substr(ssn, 3, 2)
|| case
when to_number(substr(ssn, 7, 3)) between 0 and 499
and to_number(substr(ssn, 5, 2)) between 0 and 99 then '19'
when to_number(substr(ssn, 7, 3)) between 500 and 749
and to_number(substr(ssn, 5, 2)) between 54 and 99 then '18'
when to_number(substr(ssn, 7, 3)) between 500 and 999
and to_number(substr(ssn, 5, 2)) between 0 and 39 then '20'
when to_number(substr(ssn, 7, 3)) between 900 and 999
and to_number(substr(ssn, 5, 2)) between 40 and 99 then '19'
end
|| substr(ssn, 5, 2), 'DDMMYYYY') as dob
from t42
)
where months_between(trunc(sysdate), dob) < 360;
SSN DOB AGE_IN_MONTHS AGE_IN_YEARS
----------- ---------- ------------- ------------
02029949902 1999-02-02 227 18
05050050005 2000-05-05 212 17
08089999908 1999-08-08 221 18
01121799908 2017-12-01 1 0
48089999908 1999-08-08 221 18