如何使用 Oracle 获取年、月、日的年龄
How to get age in years,months and days using Oracle
我正在尝试使用这种格式为每个人打印其年龄:
例如:19 岁 8 个月 13 天。
我在谷歌上搜索了很多,我注意到有一个特定的函数可以计算日期之间的差异 DATEDIFF
。
但是 SQL*Plus
中没有这个函数,所以我继续尝试使用 MONTHS_BETWEEN()
和一些运算符。
我的尝试:
SELECT name , ' ' ||
FLOOR(MONTHS_BETWEEN(to_date(SYSDATE),to_date(date_of_birth))/12)||' years ' ||
FLOOR(MOD(MONTHS_BETWEEN(to_date(SYSDATE),to_date(date_of_birth)),12)) || ' months ' ||
FLOOR(MOD(MOD(MONTHS_BETWEEN(to_date(SYSDATE),to_date(date_of_birth)),12),4))|| ' days ' AS "Age"
FROM persons;
我的问题取决于得到天数。我不知道我应该如何使用此函数计算天数('尝试除以 4 或 30);我觉得我的逻辑很糟糕,但我想不通,有什么想法吗?
获取 YEARS 和 MONTHS 的年龄很容易,但棘手的部分是 DAYS .
如果你能固定一个月的天数,你就能得到相同的天数SQL。例如,使用标准 SCOTT.EMP table 并假设每个月有 30
天:
SQL> SELECT SYSDATE,
2 hiredate,
3 TRUNC(months_between(SYSDATE,hiredate)/12) years,
4 TRUNC(months_between(SYSDATE,hiredate) -
5 (TRUNC(months_between(SYSDATE,hiredate)/12)*12)) months,
6 TRUNC((months_between(SYSDATE,hiredate) -
7 TRUNC(months_between(SYSDATE,hiredate)))*30) days
8 FROM emp;
SYSDATE HIREDATE YEARS MONTHS DAYS
---------- ---------- ---------- ---------- ----------
2015-10-26 1980-12-17 34 10 9
2015-10-26 1981-02-20 34 8 6
2015-10-26 1981-02-22 34 8 4
2015-10-26 1981-04-02 34 6 23
2015-10-26 1981-09-28 34 0 28
2015-10-26 1981-05-01 34 5 24
2015-10-26 1981-06-09 34 4 17
2015-10-26 1982-12-09 32 10 17
2015-10-26 1981-11-17 33 11 9
2015-10-26 1981-09-08 34 1 18
2015-10-26 1983-01-12 32 9 14
2015-10-26 1981-12-03 33 10 22
2015-10-26 1981-12-03 33 10 22
2015-10-26 1982-01-23 33 9 3
14 rows selected.
但是,请注意并非每个月都有 30
天。因此,您无法获得天数的准确性。
更新
我错过了@Alex Poole 在他接受的答案中解释的整个月的总差异。我会让这个答案让未来的读者理解关于计算天数遗漏的部分。
修改为:
TRUNC((months_between(SYSDATE,hiredate) -
TRUNC(months_between(SYSDATE,hiredate)))*30) days
有了这个:
TRUNC(SYSDATE) - add_months(hiredate, TRUNC(months_between(sysdate,hiredate)))
与 Lalit 的回答非常相似,但您可以在不假设每月 30 天的情况下获得准确的天数,方法是使用 add_months
根据整个月的总差异进行调整:
select sysdate,
hiredate,
trunc(months_between(sysdate,hiredate) / 12) as years,
trunc(months_between(sysdate,hiredate) -
(trunc(months_between(sysdate,hiredate) / 12) * 12)) as months,
trunc(sysdate)
- add_months(hiredate, trunc(months_between(sysdate,hiredate))) as days
from emp;
SYSDATE HIREDATE YEARS MONTHS DAYS
---------- ---------- ---------- ---------- ----------
2015-10-26 1980-12-17 34 10 9
2015-10-26 1981-02-20 34 8 6
2015-10-26 1981-02-22 34 8 4
2015-10-26 1981-04-02 34 6 24
2015-10-26 1981-09-28 34 0 28
2015-10-26 1981-05-01 34 5 25
2015-10-26 1981-06-09 34 4 17
2015-10-26 1982-12-09 32 10 17
2015-10-26 1981-11-17 33 11 9
2015-10-26 1981-09-08 34 1 18
2015-10-26 1983-01-12 32 9 14
2015-10-26 1981-12-03 33 10 23
2015-10-26 1981-12-03 33 10 23
2015-10-26 1982-01-23 33 9 3
你可以通过逆向计算来验证:
with tmp as (
select trunc(sysdate) as today,
hiredate,
trunc(months_between(sysdate,hiredate) / 12) as years,
trunc(months_between(sysdate,hiredate) -
(trunc(months_between(sysdate,hiredate) / 12) * 12)) as months,
trunc(sysdate)
- add_months(hiredate, trunc(months_between(sysdate,hiredate))) as days
from emp
)
select * from tmp
where today != add_months(hiredate, (12 * years) + months) + days;
no rows selected
语法:
SELECT
CONCAT(
TIMESTAMPDIFF(YEAR, ?, NOW()),
' Years,',
TIMESTAMPDIFF(MONTH, ?, NOW()) % 12,
' Months,',
FLOOR(TIMESTAMPDIFF(DAY, ?, NOW()) % 30.4375),
' Days'
) AS age
FROM
DUAL
- 输入:
代替 '?'与出生日期。例如,'1994-07-08'
- 输出:
此查询将 return 年龄 'X' 年 'Y' 个月 'Z' 天。
获取月份的另一种简化方法是-
TRUNC(MOD(months_between(sysdate,hiredate),12)) AS months
我正在尝试使用这种格式为每个人打印其年龄:
例如:19 岁 8 个月 13 天。
我在谷歌上搜索了很多,我注意到有一个特定的函数可以计算日期之间的差异 DATEDIFF
。
但是 SQL*Plus
中没有这个函数,所以我继续尝试使用 MONTHS_BETWEEN()
和一些运算符。
我的尝试:
SELECT name , ' ' ||
FLOOR(MONTHS_BETWEEN(to_date(SYSDATE),to_date(date_of_birth))/12)||' years ' ||
FLOOR(MOD(MONTHS_BETWEEN(to_date(SYSDATE),to_date(date_of_birth)),12)) || ' months ' ||
FLOOR(MOD(MOD(MONTHS_BETWEEN(to_date(SYSDATE),to_date(date_of_birth)),12),4))|| ' days ' AS "Age"
FROM persons;
我的问题取决于得到天数。我不知道我应该如何使用此函数计算天数('尝试除以 4 或 30);我觉得我的逻辑很糟糕,但我想不通,有什么想法吗?
获取 YEARS 和 MONTHS 的年龄很容易,但棘手的部分是 DAYS .
如果你能固定一个月的天数,你就能得到相同的天数SQL。例如,使用标准 SCOTT.EMP table 并假设每个月有 30
天:
SQL> SELECT SYSDATE,
2 hiredate,
3 TRUNC(months_between(SYSDATE,hiredate)/12) years,
4 TRUNC(months_between(SYSDATE,hiredate) -
5 (TRUNC(months_between(SYSDATE,hiredate)/12)*12)) months,
6 TRUNC((months_between(SYSDATE,hiredate) -
7 TRUNC(months_between(SYSDATE,hiredate)))*30) days
8 FROM emp;
SYSDATE HIREDATE YEARS MONTHS DAYS
---------- ---------- ---------- ---------- ----------
2015-10-26 1980-12-17 34 10 9
2015-10-26 1981-02-20 34 8 6
2015-10-26 1981-02-22 34 8 4
2015-10-26 1981-04-02 34 6 23
2015-10-26 1981-09-28 34 0 28
2015-10-26 1981-05-01 34 5 24
2015-10-26 1981-06-09 34 4 17
2015-10-26 1982-12-09 32 10 17
2015-10-26 1981-11-17 33 11 9
2015-10-26 1981-09-08 34 1 18
2015-10-26 1983-01-12 32 9 14
2015-10-26 1981-12-03 33 10 22
2015-10-26 1981-12-03 33 10 22
2015-10-26 1982-01-23 33 9 3
14 rows selected.
但是,请注意并非每个月都有 30
天。因此,您无法获得天数的准确性。
更新
我错过了@Alex Poole 在他接受的答案中解释的整个月的总差异。我会让这个答案让未来的读者理解关于计算天数遗漏的部分。
修改为:
TRUNC((months_between(SYSDATE,hiredate) -
TRUNC(months_between(SYSDATE,hiredate)))*30) days
有了这个:
TRUNC(SYSDATE) - add_months(hiredate, TRUNC(months_between(sysdate,hiredate)))
与 Lalit 的回答非常相似,但您可以在不假设每月 30 天的情况下获得准确的天数,方法是使用 add_months
根据整个月的总差异进行调整:
select sysdate,
hiredate,
trunc(months_between(sysdate,hiredate) / 12) as years,
trunc(months_between(sysdate,hiredate) -
(trunc(months_between(sysdate,hiredate) / 12) * 12)) as months,
trunc(sysdate)
- add_months(hiredate, trunc(months_between(sysdate,hiredate))) as days
from emp;
SYSDATE HIREDATE YEARS MONTHS DAYS
---------- ---------- ---------- ---------- ----------
2015-10-26 1980-12-17 34 10 9
2015-10-26 1981-02-20 34 8 6
2015-10-26 1981-02-22 34 8 4
2015-10-26 1981-04-02 34 6 24
2015-10-26 1981-09-28 34 0 28
2015-10-26 1981-05-01 34 5 25
2015-10-26 1981-06-09 34 4 17
2015-10-26 1982-12-09 32 10 17
2015-10-26 1981-11-17 33 11 9
2015-10-26 1981-09-08 34 1 18
2015-10-26 1983-01-12 32 9 14
2015-10-26 1981-12-03 33 10 23
2015-10-26 1981-12-03 33 10 23
2015-10-26 1982-01-23 33 9 3
你可以通过逆向计算来验证:
with tmp as (
select trunc(sysdate) as today,
hiredate,
trunc(months_between(sysdate,hiredate) / 12) as years,
trunc(months_between(sysdate,hiredate) -
(trunc(months_between(sysdate,hiredate) / 12) * 12)) as months,
trunc(sysdate)
- add_months(hiredate, trunc(months_between(sysdate,hiredate))) as days
from emp
)
select * from tmp
where today != add_months(hiredate, (12 * years) + months) + days;
no rows selected
语法:
SELECT
CONCAT(
TIMESTAMPDIFF(YEAR, ?, NOW()),
' Years,',
TIMESTAMPDIFF(MONTH, ?, NOW()) % 12,
' Months,',
FLOOR(TIMESTAMPDIFF(DAY, ?, NOW()) % 30.4375),
' Days'
) AS age
FROM
DUAL
- 输入: 代替 '?'与出生日期。例如,'1994-07-08'
- 输出: 此查询将 return 年龄 'X' 年 'Y' 个月 'Z' 天。
获取月份的另一种简化方法是-
TRUNC(MOD(months_between(sysdate,hiredate),12)) AS months