如果出生00-49,则将DDMMYY转换为DDMMYYYY

时间:2017-11-08 15:39:03

标签: oracle11g date-format

挪威社会安全号码(SSN)就像这样组成

lists = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]

print(list(my_gen(lists, 2)))
#  [(1, 6), (1, 7)]
print(list(my_gen(lists, 3)))
#  [(1, 6), (1, 7), (1, 8)]
print(list(my_gen(lists, 4)))
#  [(1, 6), (1, 7), (1, 8), (1, 9)]

我正努力将出生日期转换为日期格式DD.MM.YYYY,用于出生于1900年至1949年之间的人

substr(ssn,1,6) = ddmmyy
substr(ssn,7,3) =
Person individual numbers:
000–499 persons born 1900–1999.
500–749 persons born 1854–1899.
500–999 persons born 2000–2039.
900–999 persons born 1940–1999.

substr(ssn,11,2)=control digits

我预计121049将于12月19日返回。鉴于我可以获得的信息,如何强制oracle返回预期的日期格式?

来自维基百科:https://en.wikipedia.org/wiki/National_identification_number#Norway

  

从历史上看,这个数字是由出生日期组成的   (DDMMYY),一个三位数的个人号码和两个校验位。该   个人号码和支票数字统称为   个人号码。

     

已根据范围选择个人编号   出生的世纪:1854 - 1899年的范围是500-749,为   1900 - 1999年的范围是000-499,为2000 - 2039年   范围是500-999。 1940年至1999年期间,范围900-999也是   用于特殊目的,如从国外收养和   移民。女性甚至被分配了个人号码,而男性则是   分配奇数个人号码。

1 个答案:

答案 0 :(得分:2)

两位数年份及其隐含世纪的解释似乎都基于其价值和PIN。重叠的范围,但全年限制;所以看起来你可以使用一个检查两者的案例表达式:

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

对于该数据,基于您的两个示例和所涉及的范围,给出:

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

案例根据PIN选择一个两位数的世纪值,然后 - 因为它们重叠 - 两位数的年份范围。

如果数据设计发生变化,因此基于两位数年份的重叠不再是唯一的,那么您还有其他问题。当我们到达2040年时会发生什么事情会很有趣......

如果您的SSN与您显示的范围不匹配,请说12105050000(PIN 500,但两位数的年份不在00-39或54的范围内-99)然后case表达式将返回null,然后两位数的年份将被解释为0050.你可以通过更改格式模型使其成为错误 - 取决于它是否可能发生以及如果它可以如何处理它

你可能无论如何都可以解决这个问题,但是为了处理评论中提到的第+ 40天情景,你可以使用另一个案例表达来调整日期数字:

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