这相当于您的查询中计算“年龄”(整数)年的表达式:
FLOOR(DATEDIFF(DATE(NOW()),
DATE_ADD('1970-01-01',INTERVAL users.i_dob SECOND)
)/365.25)
这个表达式实际上是这样的形式:
FLOOR(DATEDIFF(DATE(NOW()), dob )/365.25)
其中dob
是代表用户出生日期的 DATE 值。我们dob
使用这个表达式得出:
DATE_ADD('1970-01-01',INTERVAL users.i_dob SECOND)
(这是基于一些假设,如下所述。)
选择:
此计算返回几乎相同的结果,但实际上更精确:
IF(YEAR(NOW())<=YEAR( dob ), 0,
YEAR(NOW())-YEAR( dob ) /* yeardiff and subtract 1 if now is before birthday */
- (MONTH(NOW())<MONTH( dob ) OR
(MONTH(NOW())=MONTH( dob ) AND DAY(NOW())<DAY( dob )))
)
注意:同样,在此表达式中,dob
表示实际的 MySQL DATE 值,而不是整数秒数。dob
要使用它,您将使用以下表达式替换所有五次出现的:
DATE_ADD('1970-01-01',INTERVAL users.i_dob SECOND)
更多细节:
看起来该users.i_dob
列的数据类型将日期表示为从 1970 年 1 月 1 日午夜开始的整数秒数。(鉴于这似乎对 1970 年之后的 DOB “有效”,但不是更早。所以这很可能是 (有符号)INT
或BIGINT
.(这可能是一个字符列,并且该值被隐式转换为数字。TIMESTAMP 列不允许存储早于 1970 年 1 月 1 日的日期值。)
(拥有有关所涉及列的实际数据类型的信息会有所帮助。)
鉴于列名称前导“i_”,我们将假设users.i_dob
列定义为INT
,并表示从 UTC 1970 年 1 月 1 日午夜开始的秒数。
这给出了一个有效范围的“dob”值,可以表示为大约。“1901-12-14”到“2038-01-19”
它看起来像这样的查询:
SELECT DISTINCT users.id
, users.v_first_name
, users.v_last_name
, FLOOR((TO_DAYS(NOW())- TO_DAYS(FROM_UNIXTIME(users.i_dob))) / 365.25)
FROM users
正在尝试以年为单位计算用户“年龄”。
该FROM_UNIXTIME
函数适用于 TIMESTAMP 值,因此它不适用于 1970 年 1 月 1 日之前的值。
要获取 i_dob 表示的实际 DATETIME 值,我们可以使用该DATE_ADD
函数。
DATE_ADD('1970-01-01',INTERVAL users.i_dob SECOND)
要获取该 DATETIME 值和当前日期之间的天数,我们使用以下DATEDIFF
函数:
DATEDIFF(NOW(),DATE_ADD('1970-01-01',INTERVAL users.i_dob SECOND))
(DATEDIFF 函数忽略时间组件,只对日期部分进行操作,这很可能是您想要的。查询中的计算包括时间部分,这增加了一些草率。)
从天数来看,您似乎是通过除以一年中的天数来计算年数,当 NOW() 在他们生日的一天内时,那里有一点马虎......但我不是会费心在这里证明这一点。)
所以,我认为这应该让你足够接近,
= FLOOR(DATEDIFF(DATE(NOW()),
DATE_ADD('1970-01-01',INTERVAL users.i_dob SECOND)
)/365.25)
一个人“年龄”的更精确计算确实需要比较年、月和日。如果我们只对报告非负年龄感兴趣,这样的事情会起作用:
IF(YEAR(NOW())<=YEAR( dob ), 0,
YEAR(NOW())-YEAR( dob ) /* yeardiff and subtract 1 if now is before birthday */
- (MONTH(NOW())<MONTH( dob ) OR
(MONTH(NOW())=MONTH( dob ) AND DAY(NOW())<DAY( dob )))
)
注意:该表达式中的代表“dob”dob
的 MySQL值,而不是整数秒数。DATE
注意:这个表达式将只返回非负值;它永远不会返回负年龄。
我承认这看起来有点复杂,但真正要做的是检查年龄是否至少为 1 岁,否则减去年份,然后使用条件测试(它返回一个布尔值,我们将其解释为整数 1 或0) 当当前月份和日期在生日的月份和日期之前,将差值向后调整 1 年。)
在您的情况下,要使用它,您需要dob
将该表达式中的所有五次出现替换为从整数中获取 dob 值的表达式DATE
,即
dob = DATE_ADD('1970-01-01',INTERVAL users.i_dob SECOND)
That would give a more precise result, but would be way more uglier than the other expression, which returns a nearly equivalent result.