Die Interpretation der zweistelligen Jahreszahl und ihres implizierten Jahrhunderts scheint sowohl auf ihrem Wert als auch auf der PIN zu beruhen. Die Bereiche dafür überschneiden sich, aber das ganze Jahr ist dann eingeschränkt; es sieht also so aus, als könnten Sie einen case-Ausdruck verwenden, der beides überprüft:
-- 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;
was für diese Daten, basierend auf Ihren beiden Beispielen und den betroffenen Bereichen, ergibt:
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
Der Fall wählt einen zweistelligen Jahrhundertwert basierend auf der PIN und dann – weil sie sich überschneiden – den zweistelligen Jahresbereich.
Wenn sich das Datendesign ändert, sodass die Überschneidungen aufgrund der zweistelligen Jahreszahl nicht mehr eindeutig sind, haben Sie weitere Probleme. Es wird interessant sein zu sehen, was passiert, wenn wir das Jahr 2040 erreichen...
Und wenn Sie eine SSN hatten, die nicht mit den angezeigten Bereichen übereinstimmt, sagen Sie 12105050000
(mit PIN 500, aber zweistelliger Jahreszahl weder im Bereich 00-39 noch 54-99), dann gibt der case-Ausdruck null zurück und die zweistellige Jahreszahl wird dann als 0050 interpretiert. Sie könnten stattdessen einen Fehler machen, indem Sie sie ändern das Formatmodell - hängt davon ab, ob es passieren kann und wie Sie damit umgehen wollen, wenn es passiert.
Sie können diesen Teil wahrscheinlich trotzdem herausfinden, aber um das in den Kommentaren erwähnte Szenario Tag + 40 zu handhaben, können Sie einen anderen Fallausdruck verwenden, um die Tageszahl anzupassen:
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
...