0

以下是我对 cron 的 sql 查询,其中我试图将记录从一个表保存到另一个表我只想要一个修改,我无法在我的 i_age 字段中进行修改,年龄应该保存在数据库中,但如果零来自上表然后年龄计算公式不适用,它只将零保存到 i_age 字段请让我知道我该怎么做,

谢谢,

INSERT IGNORE into z_census ( i_age)
            SELECT  IF((i_age = 0), i_age, FLOOR(DATEDIFF(DATE(NOW()),DATE_ADD('1970-01-01',INTERVAL users.i_dob SECOND))/365.25) )
            FROM users
4

1 回答 1

0

这相当于您的查询中计算“年龄”(整数)年的表达式:

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 “有效”,但不是更早。所以这很可能是 (有符号)INTBIGINT.(这可能是一个字符列,并且该值被隐式转换为数字。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.

于 2012-07-21T00:37:00.703 回答