记录两个表之间的插入(选择何时计算年龄)

时间:2012-07-20 23:05:46

标签: mysql

以下是我对cron的sql查询,其中我试图将记录从一个表保存到另一个表我只想要一个修改我无法在我的i_age字段中将年龄应该保存在数据库中但是如果为零从上一张表开始,然后年龄计算公式不适用,它只保存0到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

1 个答案:

答案 0 :(得分:0)

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

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值, NOT 表示整数秒。要使用此功能,您可以使用以下表达式替换所有五次出现的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的情况下继续前进,并表示从1月1日午夜开始的秒数,1970 UTC。

这给出了一个有效范围的“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值, NOT 表示整数秒。

注意:此表达式仅返回非负值;它永远不会回归负面年龄。

我承认这看起来有点复杂,但所有真正做的就是检查年龄不是至少1年,否则减去年份,然后使用条件测试(它返回一个布尔值,我们解释为当前月份和日期在生日的月份和日期之前时,将差值调整为1年。)

在您的情况下,要使用此功能,您需要将该表达式中所有五次出现的dob替换为从整数中获取dob DATE值的表达式,即

dob = DATE_ADD('1970-01-01',INTERVAL users.i_dob SECOND)

这会给出一个更精确的结果,但会比另一个表达式更加丑陋,后者会返回几乎相同的结果。