我正在尝试编写一个查询来选择生日在接下来7天内的数据库用户。
我做了很多研究,但我无法想出一个有效的解决方案。
生日字段存储为varchar,例如'04 / 16/93'有什么方法可以使用吗?
这是我到目前为止所做的:
SELECT *
FROM `PERSONS`
WHERE `BIRTHDAY` > DATEADD(DAY, -7, GETDATE())
我应该说得更清楚,我正在努力寻找生日而不是出生日期。所以我只是寻找几天而不是几年。
答案 0 :(得分:40)
要在接下来的7天内获得所有生日,请将出生日期与今天的年份差异添加到出生日期,然后查看是否在接下来的七天内。
SELECT *
FROM persons
WHERE DATE_ADD(birthday,
INTERVAL YEAR(CURDATE())-YEAR(birthday)
+ IF(DAYOFYEAR(CURDATE()) > DAYOFYEAR(birthday),1,0)
YEAR)
BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY);
如果您想排除今天的生日,只需将>
更改为>=
SELECT *
FROM persons
WHERE DATE_ADD(birthday,
INTERVAL YEAR(CURDATE())-YEAR(birthday)
+ IF(DAYOFYEAR(CURDATE()) >= DAYOFYEAR(birthday),1,0)
YEAR)
BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY);
-- Same as above query with another way to exclude today's birthdays
SELECT *
FROM persons
WHERE DATE_ADD(birthday,
INTERVAL YEAR(CURDATE())-YEAR(birthday)
+ IF(DAYOFYEAR(CURDATE()) > DAYOFYEAR(birthday),1,0)
YEAR)
BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY)
AND DATE_ADD(birthday, INTERVAL YEAR(CURDATE())-YEAR(birthday) YEAR) <> CURDATE();
-- Same as above query with another way to exclude today's birthdays
SELECT *
FROM persons
WHERE DATE_ADD(birthday,
INTERVAL YEAR(CURDATE())-YEAR(birthday)
+ IF(DAYOFYEAR(CURDATE()) > DAYOFYEAR(birthday),1,0)
YEAR)
BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY)
AND (MONTH(birthday) <> MONTH(CURDATE()) OR DAY(birthday) <> DAY(CURDATE()));
以下是所有查询的DEMO
答案 1 :(得分:8)
非常简单易行。不需要使用任何if条件或其他任何你只需要使用mysql的DATE_FORMAT()函数。
这是我的SQL查询
SELECT id,email ,dob FROM `users` where DATE_FORMAT(dob, '%m-%d') >= DATE_FORMAT(NOW(), '%m-%d') and DATE_FORMAT(dob, '%m-%d') <= DATE_FORMAT((NOW() + INTERVAL +7 DAY), '%m-%d')
答案 2 :(得分:6)
这是我的解决方案。如果出生日期是1月1日,今天的日期是12月31日,它也有效。
SELECT `id`, `name`, `dateofbirth`,
DATE_ADD(
dateofbirth,
INTERVAL IF(DAYOFYEAR(dateofbirth) >= DAYOFYEAR(CURDATE()),
YEAR(CURDATE())-YEAR(dateofbirth),
YEAR(CURDATE())-YEAR(dateofbirth)+1
) YEAR
) AS `next_birthday`
FROM `user`
WHERE
`dateofbirth` IS NOT NULL
HAVING
`next_birthday` BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY)
ORDER BY `next_birthday`
LIMIT 1000;
答案 3 :(得分:2)
试试这个:
Select * From persons
where (DayOfYear(birthday) >= 7
And DayOfYear(birthday) - DayOfYear(curdate()) Between 0 and 6) Or
(MOD(YEAR(curDate()),4) = 0) And MOD(YEAR(curDate()),100) != 0
And (DayOfYear(birthday) + 366 - DayOfYear(curdate())) % 366 < 7) Or
(DayOfYear(birthday) + 365 - DayOfYear(curdate())) % 365 < 7)
答案 4 :(得分:2)
我设法让它使用此查询。主要是由于Lobo的回答。
SELECT *
FROM persons
WHERE DATE_ADD(STR_TO_DATE(birthday, '%m/%d/%Y'), INTERVAL YEAR(CURDATE())-YEAR(STR_TO_DATE(birthday, '%m/%d/%Y')) YEAR)
BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY);
答案 5 :(得分:1)
在尝试获取在一段时间内即将到来的b列表时,我们可能会遇到几个问题。
当有闰年时,你有可能无法处理闰年的情况。下一个问题可能就像今天2016-12-30
一样,接下来的7天需要b&#39天。所以期末是2017
年。在这种情况下,某些条件失败。这些是非常重要的测试用例。
此线程中的大多数固定使用DAYOFYEAR()
,当您处于闰年时,它会失败。
例如。
DAYOFYEAR('2016-03-01 00:00:00')
61
DAYOFYEAR('2015-03-01 00:00:00')
60
最简单,最容易理解的方法就是这样。
这适用于闰年,而且日期范围可以跨越两年。
SELECT *
FROM `PERSONS`
WHERE
/*
Here we calculate the next coming b'day for user
and check if it is between our span
*/
CONCAT(IF(
CONCAT( YEAR(CURDATE()), substring(`BIRTHDAY`, 5, length(`BIRTHDAY`))) < CURDATE(),
YEAR(CURDATE()) + 1, /* Adds an year if already past */
YEAR(CURDATE()) /* Use this year if it is upcoming */
), substring(`BIRTHDAY`, 5, length(`BIRTHDAY`)))
BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL @tot DAY)
PS:如果你想在b&#39天的基础上订购这些,这也是最好的解决方案。您只需将其添加为字段。
答案 6 :(得分:1)
这是leap年问题的优化解决方案
SELECT *
FROM persons
WHERE DATE_FORMAT( CONCAT(YEAR(CURDATE()),'-',DATE_FORMAT(birth_date, '%m-%d') ), '%Y-%m-%d')
BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY)
答案 7 :(得分:1)
这是我遇到同样问题时所做的事情:
select * from users
where ( month(date_of_birth) > month(CURDATE())
and month(date_of_birth) < month(ADDDATE(CURDATE(),30)) )
or ( month(CURDATE()) = month(date_of_birth) and day(date_of_birth) >= day(CURDATE())
or month(ADDDATE(CURDATE(),30)) = month(date_of_birth) and day(date_of_birth) <= day(ADDDATE(CURDATE(),30)) )
or ( year(CURDATE()) > year(ADDDATE(CURDATE(),30)) and month(date_of_birth) < month(CURDATE()) and month(date_of_birth) > month(ADDDATE(CURDATE(),30)) )
答案 8 :(得分:1)
我们遇到了一个日历必须显示下一个十岁生日(包括今天的生日)的麻烦。 我已经将我刚刚找到的解决方案简化为相关部分:
SELECT first_name, last_name, birth_date,
IF (DAYOFYEAR(DATE_FORMAT(birth_date,'1980-%m-%d %T')) < DAYOFYEAR(DATE_FORMAT(NOW(),'1980-%m-%d %T')) ,
DAYOFYEAR(DATE_FORMAT(birth_date,'1980-%m-%d %T'))+368 ,
DAYOFYEAR(DATE_FORMAT(birth_date,'1980-%m-%d %T'))) AS upcomming
FROM users
WHERE birth_date IS NOT NULL AND birth_date !=0
ORDER BY upcomming ASC
LIMIT 0, 10
它将每年(包括实际)设置为闰年,因此不会出现任何问题。 如果你接近年底,它也没问题。 我对最终找到一个有效的解决方案非常满意,所以我想分享一下,也许这对其他人有用:)
P.S。:如果您不想显示今天的生日,只需在+1
之后添加DAYOFYEAR(DATE_FORMAT(NOW(),'1980-%m-%d %T'))
答案 9 :(得分:1)
Lobo上面接受的答案是有缺陷的,如果查询是在12月31日运行的,并且用户在1月1日生日,那么它们就不会匹配。
你必须为查询添加逻辑,这样,如果生日已经过了今年,你会看到下一年的生日,而不是今年的生日。详情如下:
SELECT *, IF( DAYOFYEAR( STR_TO_DATE(birthday, '%m/%d/%Y') ) < DAYOFYEAR( NOW() ),
DATE_ADD( STR_TO_DATE(birthday, '%m/%d/%Y'), INTERVAL YEAR( CURDATE() ) - YEAR( STR_TO_DATE(birthday, '%m/%d/%Y') ) + 1 YEAR ),
DATE_ADD( STR_TO_DATE(birthday, '%m/%d/%Y'), INTERVAL YEAR( CURDATE() ) - YEAR( STR_TO_DATE(birthday, '%m/%d/%Y') ) YEAR ) )
AS nextBirthday FROM persons
WHERE nextBirthday BETWEEN CURDATE() AND DATE_ADD( CURDATE(), INTERVAL 7 DAY);
答案 10 :(得分:1)
我发现这段代码工作得很好:
DATE_ADD(user_birthdate, INTERVAL YEAR(FROM_DAYS(DATEDIFF(CURDATE(), user_birthdate)-1)) + 1 YEAR) AS next_birthday
它实际上非常简单,它计算人的年龄,然后计算当前的年份生日,然后再加1年。
它基于Robert Eisele的答案,你可以在这里找到: http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html
P.S。
使用此解决方案,您可以获取昨天过生日的人(这是因为FROM_DAYS计算中的-1,但由于闰年而需要它)。这不应该考虑你太多,因为你只需要7天一个头,所以你应该添加以下条件:
HAVING next_birthday BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY)
答案 11 :(得分:0)
SELECT * from persons as p
WHERE
MOD( DAYOFYEAR(p.bday) - DAYOFYEAR(CURRENT_DATE()) + 366, 366)
BETWEEN 0 and 7
ORDER by DAYOFYEAR(p.bday) ASC
这对我有用。
答案 12 :(得分:0)
以Lobo应对闰年的答案为基础
SELECT * FROM users
WHERE DATE_ADD(dob,INTERVAL YEAR(CURDATE())-YEAR(dob)
+ IF(MONTH(CURDATE()) > MONTH(dob), 1,
IF(MONTH(CURDATE()) = MONTH(dob) AND DAY(CURDATE()) > DAY(dob), 1, 0))
YEAR)
BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY)
答案 13 :(得分:0)
因此,您可以采取的另一种方法是在点击数据库层之前再做一些工作。例如,我最近在Laravel(PHP)和Postgres项目中做到了这一点。我基本上构建了一个日期数组(即接下来的7天),并进行where in
查询以查找在这些日期生日的用户。
User::whereNotNull('birth_date')
->where('birth_date', '<=', $endDate)
->whereIn(DB::raw("to_char(birth_date, 'MMDD')"), Carbon::range($startDate, $endDate)->map(function ($date) {
return $date->format('md');
}))->get();
答案 14 :(得分:0)
这是一个简单的PHP代码&amp; SQL Query用于检索即将到来的生日。出生日期存储为DATE(YYYY-MM-DD格式)。 enter image description here
<?php
$conn = mysqli_connect('localhost', 'user', 'paasword', 'databasename');
$nod = 5; //Number of days upto which you want to retrieve birthdays
$delim = $filter = "";
for($i=0;$i<$nod;$i++){
$date = date_create(date('Y-m-d'));
date_add($date,date_interval_create_from_date_string("$i days"));
$filter .= $delim."'".date_format($date,"m-d")."'";
$delim = ", ";
}
$sql = "SELECT NAME, DOB, MOBILE, EMAIL, TITLE FROM tablename WHERE SUBSTR(DOB,6) IN ($filter) ORDER BY SUBSTR(DOB,6) ASC";
$result = mysqli_query($conn, $sql);
$i=0;
echo '
<table class="table-1 mt-2 table-responsive table-bordered">
<tr>
<th>S. No.</th>
<th>Name</th>
<th>DOB</th>
<th>MOBILE</th>
</tr>';
while($row = mysqli_fetch_array($result)){
$i++;
$dob = date('Y-').date_format(date_create($row["DOB"]),'m-d');
$day = date_format(date_create($dob),'w');
switch ($day){
case 0:
$day = "Sunday"; break;
case 1:
$day = "Monday"; break;
case 2:
$day = "Tuesday"; break;
case 3:
$day = "Wednesday"; break;
case 4:
$day = "Thursday"; break;
case 5:
$day = "Friday"; break;
case 6:
$day = "Saturday"; break;
}
echo"
<tr>
<td>".$i."</td>
<td>".$row["NAME"]."</td>
<td>".date_format(date_create($row["DOB"]),'d-m-Y')." $day</td>
<td>".$row["MOBILE"]."</td>
</tr>
";
}
echo"
</table>";
?>
答案 15 :(得分:0)
我做了很多“研究”,这是我的解决方案,我想这很容易理解!
SELECT *,
(366 + DAYOFYEAR(birth_date) - DAYOFYEAR(NOW())) % 366 as left_days
FROM `profile`
ORDER BY left_days;
答案 16 :(得分:0)
当生日发生在of年时,使用DAYOFYEAR()的任何解决方案都将存在缺陷。考虑年龄或生日时,请考虑使用TIMESTAMPDIFF()。
当前年龄可以计算为
timestampdiff(YEAR, person.date_of_birth, curdate())
通过将年龄加上出生日期来计算即将到来的生日。
DATE_ADD(
person.date_of_birth,
INTERVAL timestampdiff(YEAR, person.date_of_birth, curdate())+1 YEAR
)
将其组合在一起以解决OP的查询
select
DATE_ADD(
person.date_of_birth,
INTERVAL timestampdiff(YEAR, date_add(person.date_of_birth,INTERVAL 1 DAY), curdate())+1 YEAR
) upcoming_birthday
from person
having upcoming_birthday between curdate() and DATE_ADD(curdate(), INTERVAL 7 DAY)
请注意,我在计算年龄时已将date添加到date_of_birth,否则今天的生日将不会返回。
答案 17 :(得分:0)
我认为这个解决方案可能更简单。
创建查询字符串,例如,(我使用的是 PHP 和 MySql)
$query = "SELECT cols FROM table WHERE MONTH(DobCol)= ".date('m')." AND (DAY(DobCol) >= ".date('d')." AND DAY(DobCol) <= ".(date('d')+$NumOfDaysToCheck).")";
然后执行这个 $query。