日期减三个月oracle_【Oracle】【SQL】日期差返回几年、几个月、几天
【注】急脾气者,直接跳至SQL,以下均为废话
需求如题,这种需求在工作中并不算多,但往往系统为了让客户看着更直观,在页面上就算出来两个时间相差几年、几个月、几天的数值便于用户确认。
这两个天做一个数据迁移的工作,数据量不大,但数据质量较差,里面有大量的数据清洗的工作,其中就涉及到两个时间相差几年、几个月、几天的问题。因为这个时间差是存在数据库中的(原来系统存储的是手工写的,如:一年五个月,1年6个月,壹年,5个月等等,非常不标准,但好在两个时间都还在),所以,在清洗的时候通过两个时间计算出相差的差值。
数据库为Oracle,我们知道Oracle在时间处理上有很多函数,但没有一个函数能返回我们想要的信息。其实Oracle针对这个问题专门有几个数据类型
INTERVAL YEAR[ (years_precision)] TO MONTH
INTERVAL DAY[(days_precision)] TO SECOND[( seconds_precision)]
生产中这种数据类型用的很少,就算有类似的需求,就算这个数据类型比较合适,也会因为不常用而改用其他方式处理。
测试:
Default
## Oracle11g HR Schema下的job_history表
SQL> select * from job_history;
EMPLOYEE_ID START_DATE END_DATE JOB_ID DEPARTMENT_ID
----------- ----------- ----------- ---------- -------------
102 2001/1/13 2006/7/24 IT_PROG 60
101 1997/9/21 2001/10/27 AC_ACCOUNT 110
101 2001/10/28 2005/3/15 AC_MGR 110
201 2004/2/17 2007/12/19 MK_REP 20
114 2006/3/24 2007/12/31 ST_CLERK 50
122 2007/1/1 2007/12/31 ST_CLERK 50
200 1995/9/17 2001/6/17 AD_ASST 90
176 2006/3/24 2006/12/31 SA_REP 80
176 2007/1/1 2007/12/31 SA_MAN 80
200 2002/7/1 2006/12/31 AC_ACCOUNT 90
10 rows selected
SQL>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
## Oracle11g HR Schema下的job_history表
SQL>select *fromjob_history;
EMPLOYEE_IDSTART_DATEEND_DATEJOB_IDDEPARTMENT_ID
--------------------------------------------------------
1022001/1/132006/7/24IT_PROG60
1011997/9/212001/10/27AC_ACCOUNT110
1012001/10/282005/3/15AC_MGR110
2012004/2/172007/12/19MK_REP20
1142006/3/242007/12/31ST_CLERK50
1222007/1/12007/12/31ST_CLERK50
2001995/9/172001/6/17AD_ASST90
1762006/3/242006/12/31SA_REP80
1762007/1/12007/12/31SA_MAN80
2002002/7/12006/12/31AC_ACCOUNT90
10rowsselected
SQL>
处理起来也不算复杂,大致思路如下:
1:通过months_between获取两个日期相差的月份数并trunc取整
2:总的相差的月份数除以12,再trunc取整,返回的即为相差的年数
3:通过两个时间相减可以返回天数,【结束时间】-(【开始时间】+【相差的月份数】)=【相差的天数】
4:通过【总的月份数】-(【相差年数】*12)]=【月份数】
Default
SQL> select employee_id, y, (mc - y * 12) as m, d, start_date, end_date
2 from (select employee_id,
3 end_date - add_months(start_date, mc) as d,
4 mc,
5 trunc(case
6 when mc >= 12 then
7 mc / 12
8 else
9 0
10 end) as y,
11 start_date,
12 end_date
13 from (select employee_id,
14 trunc(months_between(end_date, start_date)) as mc,
15 start_date,
16 end_date
17 from job_history));
EMPLOYEE_ID Y M D START_DATE END_DATE
----------- ---------- ---------- ---------- ----------- -----------
102 5 6 11 2001/1/13 2006/7/24
101 4 1 6 1997/9/21 2001/10/27
101 3 4 15 2001/10/28 2005/3/15
201 3 10 2 2004/2/17 2007/12/19
114 1 9 7 2006/3/24 2007/12/31
122 0 11 30 2007/1/1 2007/12/31
200 5 9 0 1995/9/17 2001/6/17
176 0 9 7 2006/3/24 2006/12/31
176 0 11 30 2007/1/1 2007/12/31
200 4 5 30 2002/7/1 2006/12/31
10 rows selected
SQL>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
SQL>selectemployee_id,y,(mc-y *12)asm,d,start_date,end_date
2from(selectemployee_id,
3end_date-add_months(start_date,mc)asd,
4mc,
5trunc(case
6whenmc>=12then
7mc/12
8else
90
10end)asy,
11start_date,
12end_date
13from(selectemployee_id,
14trunc(months_between(end_date,start_date))asmc,
15start_date,
16end_date
17fromjob_history));
EMPLOYEE_IDYMDSTART_DATEEND_DATE
---------------------------------------------------------------
10256112001/1/132006/7/24
1014161997/9/212001/10/27
10134152001/10/282005/3/15
20131022004/2/172007/12/19
1141972006/3/242007/12/31
122011302007/1/12007/12/31
2005901995/9/172001/6/17
1760972006/3/242006/12/31
176011302007/1/12007/12/31
20045302002/7/12006/12/31
10rowsselected
SQL>
利用with子句看着可能会更清楚一些
Default
SQL> with t1 as
2 (select employee_id,
3 trunc(months_between(end_date, start_date)) as mc,
4 start_date,
5 end_date
6 from job_history),
7 t2 as
8 (select employee_id,
9 end_date - add_months(start_date, mc) as d,
10 mc,
11 trunc(case
12 when mc >= 12 then
13 mc / 12
14 else
15 0
16 end) as y,
17 start_date,
18 end_date
19 from t1),
20 t3 as
21 (select employee_id, y, (mc - y * 12) as m, d, start_date, end_date from t2)
22 select * from t3;
EMPLOYEE_ID Y M D START_DATE END_DATE
----------- ---------- ---------- ---------- ----------- -----------
102 5 6 11 2001/1/13 2006/7/24
101 4 1 6 1997/9/21 2001/10/27
101 3 4 15 2001/10/28 2005/3/15
201 3 10 2 2004/2/17 2007/12/19
114 1 9 7 2006/3/24 2007/12/31
122 0 11 30 2007/1/1 2007/12/31
200 5 9 0 1995/9/17 2001/6/17
176 0 9 7 2006/3/24 2006/12/31
176 0 11 30 2007/1/1 2007/12/31
200 4 5 30 2002/7/1 2006/12/31
10 rows selected
SQL>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
SQL>witht1as
2(selectemployee_id,
3trunc(months_between(end_date,start_date))asmc,
4start_date,
5end_date
6fromjob_history),
7t2as
8(selectemployee_id,
9end_date-add_months(start_date,mc)asd,
10mc,
11trunc(case
12whenmc>=12then
13mc/12
14else
150
16end)asy,
17start_date,
18end_date
19fromt1),
20t3as
21(selectemployee_id,y,(mc-y *12)asm,d,start_date,end_datefromt2)
22select *fromt3;
EMPLOYEE_IDYMDSTART_DATEEND_DATE
---------------------------------------------------------------
10256112001/1/132006/7/24
1014161997/9/212001/10/27
10134152001/10/282005/3/15
20131022004/2/172007/12/19
1141972006/3/242007/12/31
122011302007/1/12007/12/31
2005901995/9/172001/6/17
1760972006/3/242006/12/31
176011302007/1/12007/12/31
20045302002/7/12006/12/31
10rowsselected
SQL>
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)