web-dev-qa-db-de.com

bevorstehende Geburtstage von mySQL SELECT

Ich versuche, eine Abfrage zu schreiben, um Benutzer einer Datenbank auszuwählen, deren Geburtstage in den nächsten 7 Tagen liegen.

Ich habe viel recherchiert, aber ich kann keine funktionierende Lösung finden.

Das Geburtstagsfeld wird als varchar gespeichert, z. B. '04/16/93 '. Gibt es eine Möglichkeit, damit zu arbeiten?

Das habe ich bisher:

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

Ich hätte es klarer machen sollen, ich versuche Geburtstage zu finden, keine Geburtsdaten. Also suche ich nur Tage und Monate, nicht Jahre.

12
Danny

Um alle Geburtstage in den nächsten 7 Tagen zu erhalten, addieren Sie die Jahresdifferenz zwischen dem Geburtsdatum und dem heutigen Datum zum Geburtsdatum und ermitteln Sie, ob sie innerhalb der nächsten sieben Tage liegt.

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);

Wenn Sie die heutigen Geburtstage ausschließen möchten, ändern Sie einfach > in >=.

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()));

Hier ist eine DEMO aller Abfragen

39
Praveen Lobo

Es ist sehr einfach und unkompliziert. Keine Notwendigkeit, irgendwelche if-Bedingungen oder irgendetwas anderes zu verwenden. Sie müssen nur die DATE_FORMAT () - Funktion von mysql verwenden.

Hier ist meine SQL-Abfrage, die ist

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')

8
Rakesh

Das ist meine Lösung. Es funktioniert auch, wenn das Geburtsdatum der 1. Januar und das heutige Datum der 31. Dezember ist.

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;
6
Todor

Ich habe es geschafft, diese Abfrage zum Laufen zu bringen. Hauptsächlich dank Lobos Antwort.

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);
2
Danny

versuche dies:

 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)
2
Charles Bretana

Während wir versuchen, die Liste zu erhalten, deren Geburtstage in einer bestimmten Zeit bevorstehen, können wir uns mit einigen Problemen beschäftigen.

Wenn es ein Schaltjahr gibt, besteht die Möglichkeit, dass der Zustand, den Sie haben, den Fall der Schaltjahre nicht bewältigt. Das nächste Problem könnte sein, dass heute 2016-12-30 ist und Sie für die nächsten 7 Tage Übernachtungen benötigen. Das Ende der Periode ist also im Jahr 2017. In diesem Fall schlagen einige Bedingungen fehl. Dies sind sehr wichtige Testfälle.

Die meisten der in diesem Thread behobenen Probleme verwenden die DAYOFYEAR(), die in einem Schaltjahr fehlschlägt.

z.B.

DAYOFYEAR('2016-03-01 00:00:00') ist61.
DAYOFYEAR('2015-03-01 00:00:00') ist60

Die einfachste und leicht verständlichste Art ist dies.

  1. Berechnen Sie den nächsten bevorstehenden Tag für einen Benutzer.
  2. Dann prüfen Sie, ob der Tag in unser Sortiment kommt.

Dies funktioniert für Schaltjahre und auch die Datumsspanne in zwei Jahren.

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: Es ist auch die beste Lösung, wenn Sie diese auf Basis der Übernachtungen bestellen möchten. Sie müssen dies nur als Feld hinzufügen.

1
RRK

Die oben genannte akzeptierte Antwort von Lobo ist insofern fehlerhaft, als die Abfrage am 31. Dezember ausgeführt wird und der Benutzer am 1. Januar Geburtstag hat, dass sie nicht übereinstimmt.

Sie müssen der Abfrage Logik hinzufügen, damit Sie, wenn der Geburtstag dieses Jahr bereits vergangen ist, den Geburtstag von NEXT YEAR betrachten, nicht den diesjährigen. Details unten:

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);
1
Tom McQuarrie

Das habe ich getan, als ich vor demselben Problem stand:

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)) )
1
VIVEK SEDANI

Wir hatten Probleme mit einem Kalender, der die nächsten zehn Geburtstage (einschließlich der heutigen Geburtstage) anzeigen musste. Ich habe die Lösung, die ich gerade gefunden habe, auf die relevanten Teile reduziert:

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

Es setzt jedes Jahr (einschließlich des tatsächlichen) auf ein Schaltjahr um, so dass es keine Probleme damit geben wird. Wenn Sie sich dem Ende des Jahres nähern, ist das auch kein Problem. Ich bin ziemlich fest entschlossen, endlich eine funktionierende Lösung zu finden, also wollte ich diese teilen, vielleicht ist sie für jemanden nützlich :)

P .: Wenn Sie die heutigen Geburtstage nicht anzeigen möchten, fügen Sie einfach einen +1 nach DAYOFYEAR(DATE_FORMAT(NOW(),'1980-%m-%d %T')) ein.

1
Fanmade

Ich habe festgestellt, dass dieser Code wirklich gut funktioniert:

DATE_ADD(user_birthdate, INTERVAL YEAR(FROM_DAYS(DATEDIFF(CURDATE(), user_birthdate)-1)) + 1 YEAR) AS next_birthday 

es ist eigentlich ganz einfach, es berechnet das Alter der Person, dann den Geburtstag des aktuellen Jahres und addiert dann 1 Jahr.

es basiert auf der Antwort von Robert Eisele, die Sie hier finden können: http://dev.mysql.com/doc/refman/5.1/de/date-and-time-functions.html

p.s.

mit dieser Lösung können Sie Personen abrufen, die gestern Geburtstag hatten (weil -1 in der Berechnung von FROM_DAYS ist, dies ist jedoch aufgrund der Schaltjahre erforderlich). Dies sollte Sie nicht zu sehr berücksichtigen, da Sie nur 7 Tage Kopf haben möchten, und fügen Sie einfach die folgende Bedingung hinzu:

HAVING next_birthday BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY) 
1
Roey

Ein anderer Ansatz, den Sie ergreifen können, besteht darin, ein wenig mehr Arbeit zu erledigen, bevor Sie auf die Datenbankebene zugreifen. Zum Beispiel habe ich dies kürzlich in einem Laravel (PHP) - und Postgres-Projekt getan. Ich habe im Grunde eine Reihe von Daten aufgebaut (dh die nächsten 7 Tage) und eine where in-Abfrage durchgeführt, um Benutzer mit Geburtstagen an diesen Daten zu finden.

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();
0
Jonathan

Ich habe viel "recherchiert" und hier ist meine Lösung.

SELECT *,
(366 + DAYOFYEAR(birth_date) - DAYOFYEAR(NOW())) % 366 as left_days
FROM `profile`
ORDER BY left_days;

Hier ist eine einfache PHP Code & SQL-Abfrage, um anstehende Geburtstage abzurufen. Das Geburtsdatum wird als DATE (JJJJ-MM-TT-Format) gespeichert. Bildbeschreibung hier eingeben

<?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>";
?>
0
Ankit Verma

Ausgehend von Lobos Antwort auf die Schaltjahre

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)
0
Tinnin
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

Das funktioniert für mich.

0