Fortolkningen af det tocifrede årstal og dets underforståede århundrede synes at være baseret både på dets værdi og PIN-koden. Områderne for dette overlapper hinanden, men hele året er derefter begrænset; så det ser ud til, at du kan bruge et kasusudtryk, der kontrollerer begge dele:
-- 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;
som for disse data, baseret på dine to eksempler og de involverede områder, giver:
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
Sagen vælger en tocifret århundredeværdi baseret på pinkoden og derefter - fordi de overlapper - det tocifrede årstal.
Hvis datadesignet ændres, så overlapningerne ikke længere er unikke baseret på det tocifrede årstal, har du yderligere problemer. Det bliver interessant at se, hvad der sker, når vi når 2040...
Og hvis du havde et SSN, der ikke matchede de intervaller, du har vist, så sig 12105050000
(med PIN 500, men to-cifret år, hverken i intervallet 00-39 eller 54-99), så vil kasusudtrykket returnere null, og det to-cifrede år vil så blive fortolket som 0050. Du kan i stedet lave fejl ved at ændre formatmodellen - afhænger af, om det kan ske, og hvordan du vil håndtere det, hvis det sker.
Du kan sikkert finde ud af dette alligevel, men for at håndtere dag+40-scenariet nævnt i kommentarer, kan du bruge et andet kasusudtryk til at justere dagnummeret:
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
...