0

以下は、あるテーブルから別のテーブルにレコードを保存しようとしている cron の sql クエリです。i_age フィールドで作成できなかった 1 つの変更が必要です前の表の場合、年齢計算式は適用されず、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 値を表しますこれを使用するには、 の 5 つのオカレンスすべてdobを次の式に置き換えます。

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

詳細:

列のデータ型はusers.i_dob、日付を 1970 年 1 月 1 日の午前 0 時からの整数秒数として表しているように見えます (これが 1970 年以降の DOB では「機能している」ように見えますが、それ以前ではないようです。したがって、これはおそらく ( (これは文字列であり、値が暗黙的に数値に変換されている可能性があります。TIMESTAMP 列では、1970 年 1 月 1 日より前の日付値を格納することはできません。INT)BIGINT

(関係する列の実際のデータ型に関する情報を持っていると、多少は役に立ちます。)

列名の先頭に「i_」が付いているため、users.i_dob列が として定義されINT、UTC 1970 年 1 月 1 日の午前 0 時からの秒数を表すと仮定して先に進みます。

これにより、「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 関数は時間コンポーネントを無視し、日付部分のみを操作します。これは、おそらく希望どおりです。クエリ内の計算には時間部分が含まれているため、少しずさんになります。)

日数から、1 年の日数で割って年を計算しているように見えますが、NOW() が誕生日の 1 日以内にある場合、そこには少しずさんな部分があります... しかし、私はそうではありませんここでそれを実証することに煩わされます。)

だから、これで十分に近づくはずだと思います。

= 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」を表す MySQL 値を表しますdobDATE

注: この式は負でない値のみを返します。負の年齢を返すことはありません。

これが少し複雑に見えることは認めますが、実際に行っていることは、年齢が少なくとも 1 歳でないことを確認し、それ以外の場合は年齢を引き、条件付きテスト (整数 1 または整数として解釈するブール値を返す) を使用することだけです。 0) 現在の月と日が誕生日の月と日より前の場合、差を 1 年戻して調整します。)

あなたの場合、これを使用するにはdob、その式の 5 回の出現すべてを、整数から dobDATE値を取得する式に置き換える必要があります。

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

これにより、より正確な結果が得られますが、ほぼ同等の結果を返す他の式よりもはるかに醜いものになります。

于 2012-07-21T00:37:00.703 に答える