De interpretatie van het tweecijferige jaartal en de impliciete eeuw lijkt te zijn gebaseerd op zowel de waarde als de PIN. De marges daarvoor overlappen, maar het volledige jaar is dan beperkt; dus het lijkt erop dat u een hoofdletteruitdrukking kunt gebruiken die beide controleert:
-- CTE for dummy data
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 '06063999906' from dual
union all select '07074090007' from dual
union all select '08089999908' from dual
)
select ssn, to_date(substr(ssn, 1, 4)
|| 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;
die voor die gegevens, op basis van uw twee voorbeelden en de betrokken bereiken, het volgende geeft:
SSN DOB
----------- ----------
12104900000 1949-10-12
12105099999 1950-10-12
01010000001 1900-01-01
02029949902 1999-02-02
03035450003 1854-03-03
04049974904 1899-04-04
05050050005 2000-05-05
06063999906 2039-06-06
07074090007 1940-07-07
08089999908 1999-08-08
De zaak kiest een tweecijferige eeuwwaarde op basis van de pincode en vervolgens - omdat ze elkaar overlappen - het jaarbereik van twee cijfers.
Als het gegevensontwerp verandert, zodat de overlappingen niet langer uniek zijn op basis van het tweecijferige jaartal, hebt u nog meer problemen. Het zal interessant zijn om te zien wat er gebeurt als we 2040 bereiken...
En als je een SSN had die niet overeenkwam met de bereiken die je hebt getoond, zeg dan 12105050000
(met PIN 500, maar tweecijferig jaar niet in het bereik 00-39 of 54-99) dan retourneert de hoofdletterexpressie null en het tweecijferige jaar wordt dan geïnterpreteerd als 0050. U kunt in plaats daarvan een fout maken door te wijzigen het formaatmodel - hangt ervan af of het kan gebeuren en hoe je het wilt aanpakken als het gebeurt.
Je kunt dit waarschijnlijk hoe dan ook uitvogelen, maar om het in opmerkingen genoemde dag+40-scenario aan te pakken, kun je een andere hoofdletterexpressie gebruiken om het dagnummer aan te passen:
select ssn, to_date(
case
when substr(ssn, 1, 2) > 31 then to_char(to_number(substr(ssn, 1, 2)) - 40, 'FM99')
else substr(ssn, 1, 2)
end
|| substr(ssn, 3, 2)
|| case
when to_number(substr(ssn, 7, 3)) between 0 and 499
...