Oracle to_date,从MM-DD-YYYY中减去DDMMYY

时间:2018-01-09 13:59:36

标签: sql oracle date

我试图在SQL查询中让每个未满30岁的人。我在我的数据库中的出生日期是DDMMYY格式,我试图从SYSDATE中减去这个(10957是30年内的天数):

 ((TO_DATE(SYSDATE, 'MM-DD-YYYY') 
  - TO_DATE(BIRTH_DATE_FROM_DB, 'DDMMYY'), 'MM-DD-YYYY')) < 10957 

显然有一个问题是减去没有世纪信息的日期。这是社会安全号码的出生日期部分,因此我能够根据该号码的另一部分来确定它是1900年代还是2000年代。有没有办法在此基础上插入额外的YY?

以下是我用来确定世纪的代码(挪威社会安全号码开头500以上的人在2000年以后出生):

(SUBSTR(PERSON_NR, 1, 3) > 499
AND LENGTH(PERSON_NR) = 5))

我知道这是一个复杂的问题,也许很难给出确切的答案,但如果你能指出我正确的方向,我感激不尽。

2 个答案:

答案 0 :(得分:2)

使用case when并连接字符串:

with t (person, person_nr, birth_date_from_db) as (
    select 'Mark', '501ABC', '300403' from dual union all
    select 'Paul', '417PQR', '300403' from dual )
-- end of test data    
select person, person_nr,
       months_between(
         trunc(sysdate),
         to_date(substr(birth_date_from_db, 1, 4)
           || case when substr(person_nr, 1, 3) > 499 then '20' else '19' end
           || substr(birth_date_from_db, 5, 2), 'DDMMYYYY')) / 12 as age
  from t

马克14岁,保罗114:

PERSON PERSON_NR        AGE
------ --------- ----------
Mark   501ABC    14.6935483
Paul   417PQR    114.693548

答案 1 :(得分:2)

Norwegian identification number所述,in this question比您建议的更复杂。你可以从中调整答案;使用CTE在该答案上生成相同的虚拟数据加上几个D数字(并且没有无用的未来日期值):

import xlsxwriter
import xlrd

def remove_duplicates():

read_file = xlrd.open_workbook('Original.xlsx')
write_file = xlsxwriter.Workbook ('Removed_Duplicates.xlsx')

for sheet in read_file.sheets():
    no_rows = sheet.nrows
    no_cols = sheet.ncols
    name = sheet.name
    gen_sheets = write_file.add_worksheet(name)
    line_list = []
    r = 0
    for row in range(0, no_rows):
        line_sublist = [sheet.cell(row, col).value for col in range(0, no_cols)]
        if line_sublist not in line_list:
            line_list.append(line_sublist)
            for col in range(0, no_cols):
                gen_sheets.write(r,col,line_sublist[col])
            r = r + 1
write_file.close()

返回十二个虚拟值中的五个:

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 '07074090007' from dual
  union all select '08089999908' from dual
  union all select '01121799908' from dual
  union all select '48089999908' from dual
  union all select '52104900000' from dual
)
select ssn
from t42
where months_between(trunc(sysdate), to_date(
      case
        when to_number(substr(ssn, 1, 2)) > 31
          then to_char(to_number(substr(ssn, 1, 2)) - 40, 'FM00')
        else substr(ssn, 1, 2)
      end
    || substr(ssn, 3, 2)
    || 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')
  ) < 360;

或转换日期和年龄:

SSN        
-----------
02029949902
05050050005
08089999908
01121799908
48089999908