15

我正在尝试编写一个查询来选择生日在未来 7 天内的数据库用户。

我做了很多研究,但我无法提出一个可行的解决方案。

生日字段存储为 varchar 例如 '04/16/93' 有什么办法可以处理这个吗?

这是我到目前为止所拥有的:

SELECT * 
FROM   `PERSONS` 
WHERE  `BIRTHDAY` > DATEADD(DAY, -7, GETDATE()) 

我应该说得更清楚,我试图找到生日而不是出生日期。所以我只是在寻找几天和几个月而不是几年。

4

18 回答 18

52

要获取未来 7 天内的所有生日,请将出生日期与今天之间的年份差添加到出生日期,然后查找它是否在接下来的 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

于 2013-09-11T17:50:37.670 回答
12

它非常容易和简单。无需使用任何 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')

于 2018-05-31T06:10:23.953 回答
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;
于 2015-01-17T13:41:13.283 回答
4

我做了很多“研究”,这是我的解决方案,我想这很容易理解!

SELECT *,
(366 + DAYOFYEAR(birth_date) - DAYOFYEAR(NOW())) % 366 as left_days
FROM `profile`
ORDER BY left_days;
于 2018-12-27T09:01:17.140 回答
3

我发现这段代码工作得很好:

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

ps

使用此解决方案,您可能会获取昨天过生日的人(这是因为 FROM_DAYS 计算中的 -1,但由于闰年而需要它)。这不应该考虑你太多,因为你只想要 7 天,所以你应该添加以下条件:

HAVING next_birthday BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY) 
于 2013-12-04T08:24:30.353 回答
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)
于 2013-09-11T17:58:52.440 回答
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);
于 2013-09-11T19:55:31.927 回答
1

上面接受的 Lobo 的答案是有缺陷的,如果查询是在 12 月 31 日运行的,并且用户的生日是 1 月 1 日,那么他们将不会被匹配。

您必须在查询中添加逻辑,这样,如果今年的生日已经过去,您将查看 NEXT YEAR 的生日,而不是今年的生日。详情如下:

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);
于 2014-05-23T16:25:06.007 回答
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)) )
于 2015-02-06T19:53:09.610 回答
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

它将每年(包括实际)设置为闰年,因此不会有任何问题。如果你接近年底,那也没有问题。我很高兴终于找到了一个可行的解决方案,所以我想分享这个,也许它对其他人有用:)

PS:如果不想显示今天的生日,就在+1后面加一个DAYOFYEAR(DATE_FORMAT(NOW(),'1980-%m-%d %T'))

于 2014-12-03T11:38:44.540 回答
1

当出生日期发生在闰年时,任何使用 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_of_birth 中添加了一天,否则将不会返回今天的生日。

于 2020-11-07T03:54:59.543 回答
1

这是闰年问题的优化解决方案

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)
于 2020-07-28T20:28:38.413 回答
1

在尝试获取在一段时间内即将迎来生日的名单时,我们可能会遇到几个问题。

当有闰年时,您的条件有可能无法处理闰年的情况。下一个问题可能就像今天2016-12-30一样,接下来的 7 天你需要 b'days。所以期间的结束是在 year 2017。在这种情况下,某些条件会失败。这些都是非常重要的测试用例。

此线程中的大多数修复程序DAYOFYEAR()都在闰年使用 which 失败。

例如。

DAYOFYEAR('2016-03-01 00:00:00')61
DAYOFYEAR('2015-03-01 00:00:00')60

最简单和最容易理解的方式就是这个。

  1. 为用户计算下一个即将到来的 b'day。
  2. 然后检查这一天是否在我们的范围内。

这适用于闰年以及两年内的日期范围。

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'days 的基础上订购这些,这也是最好的解决方案。您只需要将其添加为字段。

于 2016-04-13T12:56:05.727 回答
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

这对我有用。

于 2015-04-30T23:17:23.193 回答
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)
于 2016-09-07T14:22:49.900 回答
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();
于 2017-12-13T18:45:24.207 回答
0

这是一个简单的 PHP 代码和 SQL 查询,用于检索即将到来的生日。其中出生日期存储为 DATE(YYYY-MM-DD 格式)。在此处输入图像描述

<?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>";
?>
于 2018-05-16T19:29:12.620 回答
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。

于 2021-02-12T06:15:29.000 回答