sql >> Base de Datos >  >> RDS >> Oracle

Convertir DDMMAA a DDMMAAAA si nació 00-49

La interpretación del año de dos dígitos y su siglo implícito parece basarse tanto en su valor como en el PIN. Los rangos para eso se superponen, pero luego se restringe el año completo; por lo que parece que puede usar una expresión de mayúsculas y minúsculas que verifique ambos:

-- 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;

que para esos datos, según sus dos ejemplos y los rangos involucrados, da:

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

El caso elige un valor de siglo de dos dígitos basado en el PIN y luego, debido a que se superponen, el rango de año de dos dígitos.

Si el diseño de datos cambia para que las superposiciones ya no sean únicas según el año de dos dígitos, tiene más problemas. Será interesante ver qué sucede cuando lleguemos a 2040...

Y si tenía un SSN que no coincidía con los rangos que mostró, diga 12105050000 (con PIN 500, pero el año de dos dígitos no está en el rango 00-39 o 54-99), entonces la expresión de mayúsculas y minúsculas devolverá nulo y el año de dos dígitos se interpretará como 0050. En su lugar, podría cometer un error cambiando el modelo de formato:depende de si puede suceder y cómo desea manejarlo si sucede.

Probablemente pueda resolver esto de todos modos, pero para manejar el escenario de día + 40 mencionado en los comentarios, puede usar otra expresión de caso para ajustar el número de día:

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
...