2016-05-06 22 views
6

Dato questo schema in un database Postgres:Come calcolare il prossimo compleanno data una data di nascita?

CREATE TABLE person (
    id serial PRIMARY KEY, 
    name text, 
    birth_date date, 
); 

Come dovrei interrogare il tavolo per ottenere la data di prossimo compleanno di ogni persona dopo oggi?

Ad esempio se Bob's birth_date è il 2000-06-01, il suo prossimo compleanno sarà il 2016-06-01.

Nota: non sto cercando il birth_date + un predefinito interval ma piuttosto il prossimo anniversario della nascita di una persona.

ho scritto l'equivalente in Python:

def next_birthday(self): 
    today = datetime.date.today() 
    next_birthday = self.birth_date.replace(year=today.year) 
    if next_birthday < today: 
     next_birthday = next_birthday.replace(year=today.year + 1) 
    return next_birthday 

Tuttavia mi piacerebbe vedere se Postgres può fare questo in modo più performante.

+0

@PetrHejda - quella risposta seleziona i compleanni in un dato intervallo di date (1 settimana da oggi). Sto cercando di ottenere il prossimo anniversario del compleanno di ogni persona. – ghickman

+0

@Simile: quella risposta filtra le righe, mentre sto cercando di calcolare il prossimo compleanno imminente per ogni persona. – ghickman

+0

E il 29 febbraio, cosa dovrebbe restituire? Se non c'è il 29 febbraio l'anno prossimo, dovrebbe tornare il 28 febbraio, 1 marzo o il prossimo 29 febbraio? – Peter

risposta

4
select birth_date, 
     cast(birth_date + ((extract(year from age(birth_date)) + 1) * interval '1' year) as date) as next_birthday 
from person 
where name = 'Bob' 

L'espressione (extract(year from age(birth_date)) + 1) * interval '1' year calcola l'età al prossimo compleanno in anni (completi). Aggiungendo questo alla data di nascita, questo dà il prossimo compleanno.

Il cast è necessario per ottenere un vero date indietro, perché date + interval restituisce un timestamp (inclusa un'ora).

Se si rimuove la condizione where, si ottengono tutti i "prossimi" compleanni.

È inoltre possibile ottenere un elenco dei compleanni imminenti, ad es. i prossimi 30 giorni usando qualcosa del genere:

select next_birthday, 
     next_birthday - current_date as days_until_next 
from (
    select birth_date, 
     cast(birth_date + ((extract(year from age(birth_date)) + 1) * interval '1' year) as date) as next_birthday 
    from person 
) as upcoming 
where upcoming.next_birthday <= current_date + 30 
order by next_birthday; 
+0

Fantastico :) Come estenderesti/modificheresti questa query in modo che non solo ti fornisse un elenco dei compleanni successivi, ma anche dei compleanni in 2, 3, 4 .. anni? In questo caso vorrei fare 'LIMIT 50' .. grazie in anticipo! –

-1

SELECT data birth_date + intervallo "1 anno" come next_birthday da persona;

+0

Questo dà solo il primo compleanno della persona, ma mi rendo conto che la mia domanda è ambigua su questo punto e si aggiornerà! – ghickman

0
SELECT 
    birth_date 
    + 
    cast(
     date_part('year', current_date) 
     - 
     date_part('year', birth_date) 
     + 
     CASE 
      WHEN 
       date_part('month', birth_date) < 
         date_part('month', current_date) 
       OR (
        date_part('month', birth_date) = 
          date_part('month', current_date) 
        AND 
        date_part('day', birth_date) < 
          date_part('day', current_date) 
       ) 
      THEN 1 
      ELSE 0 
     END || ' year' as interval) 
FROM person; 
Problemi correlati