すべてのユーザーの誕生日を UNIX タイムスタンプとして保存しており、その日が誕生日のユーザーに毎日電子メールを送信したいと考えています。
今日の日付の誕生日を含むすべての行を取得する MySQL クエリを作成する必要があります。
これはかなり単純なはずですが、複雑にしすぎているだけかもしれません。
すべてのユーザーの誕生日を UNIX タイムスタンプとして保存しており、その日が誕生日のユーザーに毎日電子メールを送信したいと考えています。
今日の日付の誕生日を含むすべての行を取得する MySQL クエリを作成する必要があります。
これはかなり単純なはずですが、複雑にしすぎているだけかもしれません。
これはうまくいくはずです:
SELECT *
FROM USERS
WHERE
DATE_FORMAT(FROM_UNIXTIME(birthDate),'%m-%d') = DATE_FORMAT(NOW(),'%m-%d')
これは、プロパティがうるう年を考慮に入れ、2 月 29 日が誕生日のユーザーと 3 月 1 日が同じユーザーを常に提供するという回答です。
SELECT *
FROM USERS
WHERE
DATE_FORMAT(FROM_UNIXTIME(birthDate),'%m-%d') = DATE_FORMAT(NOW(),'%m-%d')
OR (
(
DATE_FORMAT(NOW(),'%Y') % 4 <> 0
OR (
DATE_FORMAT(NOW(),'%Y') % 100 = 0
AND DATE_FORMAT(NOW(),'%Y') % 400 <> 0
)
)
AND DATE_FORMAT(NOW(),'%m-%d') = '03-01'
AND DATE_FORMAT(FROM_UNIXTIME(birthDate),'%m-%d') = '02-29'
)
これはますますコードゴルフの質問になるため、うるう年の処理を含むこれを解決するための私のアプローチは次のとおりです。
select *
from user
where (date_format(from_unixtime(birthday),"%m-%d") = date_format(now(),"%m-%d"))
or (date_format(from_unixtime(birthday),"%m-%d") = '02-29'
and date_format('%m') = '02'
and last_day(now()) = date(now())
);
説明: 最初の where 句は、誰かの誕生日が今日かどうかをチェックします。2 つ目は、現在の日が 2 月の最終日に等しい場合にのみ、誕生日が 2 月 29 日である人だけを選択するようにします。
例:
SELECT last_day('2009-02-01'); -- gives '2009-02-28'
SELECT last_day('2000-02-01'); -- gives '2009-02-29'
SELECT last_day('2100-02-01'); -- gives '2100-02-28'
これはうるう年のケースをカバーする必要があり、内部の日付メカニズムを使用します。
基本的には、2 つの日付の間の年を生年月日に加算し、現在の日付と等しいかどうかをチェックします。
WHERE dob + INTERVAL (YEAR(CURDATE()) - YEAR(dob)) YEAR = CURDATE();
テスト:
SELECT '2012-02-29'
+ INTERVAL (YEAR('2015-02-28') - YEAR('2012-02-29')) YEAR
= '2015-02-28'; /* 1, is birthday */
SELECT '2012-02-28'
+ INTERVAL (YEAR('2015-02-28') - YEAR('2012-02-28')) YEAR
= '2015-02-28'; /* 1, is birthday */
SELECT '2012-02-28'
+ INTERVAL (YEAR('2016-02-29') - YEAR('2012-02-28')) YEAR
= '2016-02-29'; /* 0, is NOT birthday */
SELECT '2012-02-29'
+ INTERVAL (YEAR('2016-02-29') - YEAR('2012-02-29')) YEAR
= '2016-02-29'; /* 1, is birthday */
私はこの問題に遭遇し、この単純なコードを使用してNOW();
$myquery = "SELECT username FROM $tblusers WHERE NOW() = bd";
結果は今日の誕生日なので、その後、誕生日にユーザーにメールを送信することに取り組んでいます。
私は DATE だけを使用してユーザーの誕生日を保存しているのでyy:mm:dd
、常に .
以下の答えは実際には機能しません。1 年が 365.24 日 (閏日である場合もある) であるという事実は考慮されていないため、ユーザーの生年月日との実際の比較は控えめに言っても複雑です。私は歴史的な理由でそれを残しています。
他の答えはうまくいくはずですが、行がたくさんある場合など、わずかな最適化が必要な場合は、クエリをタイムスタンプ秒で直接表現する方がよいでしょう。リレーションを使用できます (タイムゾーンを考慮しているため、少し複雑です)。
today_starts = UNIX_TIMESTAMP(NOW()) - TIMESTAMPDIFF(SECOND, DATE(NOW()), NOW()) today_ends = today_starts + 86400
次に、タイムスタンプがそれらの値の間にあるレコードを選択します。
これが私の貢献です
SELECT
DAYOFYEAR(CURRENT_DATE)-(dayofyear(date_format(CURRENT_DATE,'%Y-03-01'))-60)=
DAYOFYEAR(the_birthday)-(dayofyear(date_format(the_birthday,'%Y-03-01'))-60)
FROM
the_table
ビット '(dayofyear(date_format(current_date,'%Y-03-01'))-60)' は、3 月 1 日が dayofyear 番号 61 になるため、うるう年には 1 を返し、通常の年には 0 を返します。
ここからは、余分な日を「私の誕生日」の計算から差し引くだけです。
楽しみ :)
select p.birthday,
CASE YEAR(p.birthday)%4 + MONTH(p.birthday)-2 + dayofmonth(p.birthday)-29 WHEN 0 THEN 1 ELSE 0 END as isBirthday29Feb,
CASE YEAR(now())%4 WHEN 0 THEN 1 ELSE 0 END as isThisYearLeap,
IF(YEAR(p.birthday)%4 + MONTH(p.birthday)-2 + dayofmonth(p.birthday)-29=0 AND YEAR(now())%4 != 0,
DATE_ADD(DATE_ADD(p.birthday, INTERVAL 1 DAY), INTERVAL YEAR(NOW())-YEAR(p.birthday) YEAR) ,
DATE_ADD(p.birthday, INTERVAL YEAR(NOW())-YEAR(p.birthday) YEAR)
)as thisYearBirthDay
from person p;
これにより、現在の年に従って計算された人の誕生日が得られます。その後、他の計算に使用できます。列isBirthday28Feb
と列isThisYearLeap
は、ソリューションを説明するためだけに与えられています。
私はSaggi Malachiの答えを取り、その年にそのような日がない場合、2月29日の誕生日を2月28日の日付に含めるように拡張しました.
SELECT *
FROM USERS
WHERE
DATE_FORMAT(FROM_UNIXTIME(birthDate),'%m-%d') = DATE_FORMAT(NOW(),'%m-%d')
UNION
SELECT *
FROM USERS
WHERE
DATE_FORMAT(NOW(),'%Y')%4 != 0 AND DATE_FORMAT(NOW(),'%m-%d')='02-28' and DATE_FORMAT(FROM_UNIXTIME(birthDate),'%m-%d') = '02-29'
私はSaggiの答えを受け取り、次の7日間の誕生日を表示するように変更することを考えました.それはうるう年の問題もうまく解決することに気付きました:)
SELECT *
FROM USERS
WHERE
DATE_FORMAT(FROM_UNIXTIME(birthDate),'%m-%d') >= DATE_FORMAT(NOW(),'%m-%d') AND
DATE_FORMAT(FROM_UNIXTIME(birthDate),'%m-%d') < DATE_FORMAT(NOW()+INTERVAL 1 DAY,'%m-%d')
上限は含まれていないことに注意してください。うるう年の場合、'02-28' と '02-29' の間には何もありませんが、うるう年以外の場合、'02-29' は '02-28' と '03-01' の間にあります。
SELECT *
FROM USERS
WHERE
DATE_FORMAT(FROM_UNIXTIME(birthDate),'%m-%d') BETWEEN
DATE_FORMAT(NOW(),'%m-%d') AND DATE_FORMAT(NOW()+INTERVAL 7 DAY,'%m-%d')
set @now=now();
select * from user where (month(birthday) = month(@now) and day(birthday) = day(@now)) or
(month(birthday) = 2 and day(birthday) = 29 and month(@now) = 2 and day(@now) = 28 and
month(date_add(@now, interval 1 day)) = 3);
今日の日付に一致するすべての行を選択できませんでしたか? FROM_UNIXTIME() 関数を使用して UNIX タイムスタンプを日付に変換することもできます。
mysql> SELECT FROM_UNIXTIME(1196440219); -> '2007-11-30 10:30:19'