Toon posts:

[sql] aankomende verjaardagen kwestie

Pagina: 1
Acties:
  • 408 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Oplossing reeds gevonden, staat hier (verderop in topic) vermeld

Heb er al heel wat topics @ GoT over gelezen na een goede zoekactie, maar helemaal duidelijk wordt het me niet. Ik heb eenen tabel met NAW + geboortedata.
Ik zoek nu de mensen die jarig zijn vanaf (en met-) morgen, tot en met over 30 dagen vanaf vandaag.

Het probleem zit hem in het feit dat je een vergelijking moet doen met datums zónder dat je daarbij gebruik maakt van het jaartal. Wat ik al heb;

code:
1
2
3
4
5
6
7
SELECT
voornaam,
DATE_FORMAT(NOW(), "%m-%d") AS vandaag,
DATE_FORMAT(NOW() + INTERVAL 60 DAY, "%m-%d") AS over30dagen
FROM nawdata
WHERE
?


Op de plaats van het vraagteken moet een voorwaarde komen die voldoet aan;
"de [geboortedatum(maand+dag, zónder jaar)] moet tussen [vandaag] en [over30dagen] zitten".

Echter, dat krijg ik niet voor elkaar.
Ik werk overigens met MySQL.

[ Voor 25% gewijzigd door Verwijderd op 29-11-2005 17:08 ]


  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 23:21

mulder

ik spuug op het trottoir

En hier mee dan:
http://dev.mysql.com/doc/...e-and-time-functions.html

[ Voor 3% gewijzigd door mulder op 29-11-2005 15:12 ]

oogjes open, snaveltjes dicht


  • Maasluip
  • Registratie: April 2002
  • Laatst online: 22-04 15:59

Maasluip

Kabbelend watertje

Ik begrijp wat je selekteert niet helemaal. Als output krijg je in jouw selectie

ivy11-2901-28
maasluip11-2901-28

Is dat wat je wil?
Waarschijnlijk wil je iets als
code:
1
2
3
4
SELECT voornaam,
       DATE_FORMAT(geboortedatum, "%m-%d")
  FROM nawdata
 WHERE DATE_FORMAT(geboortedatum, "%m-%d") between DATE_FORMAT(NOW(), "%m-%d") and DATE_FORMAT(NOW()+60, "%m-%d")

[ Voor 7% gewijzigd door Maasluip op 29-11-2005 15:14 ]

Signatures zijn voor boomers.


  • kenneth
  • Registratie: September 2001
  • Niet online

kenneth

achter de duinen

Dat gaat volgens mij vanaf 1 november fout ...

Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.


Verwijderd

Topicstarter
Maasluip schreef op dinsdag 29 november 2005 @ 15:14:
Ik begrijp wat je selekteert niet helemaal. Als output krijg je in jouw selectie

ivy11-2901-28
maasluip11-2901-28

Is dat wat je wil?
Waarschijnlijk wil je iets als
code:
1
2
3
4
SELECT voornaam,
       DATE_FORMAT(geboortedatum, "%m-%d")
  FROM nawdata
 WHERE DATE_FORMAT(geboortedatum, "%m-%d") between DATE_FORMAT(NOW(), "%m-%d") and DATE_FORMAT(NOW()+60, "%m-%d")
Op het gezicht is die query precies wat ik wil, en in theorie ook (owel; als je logisch nadenkt, is dat precies wat je wilt). Ik heb alleen van het stuk NOW()+60 het volgende gemaakt, NOW() + INTERVAL 60 DAY omdat ik niet zeker wist of je NOW() kan verhogen met een integer.

Probleem is alleen het volgende, ik heb het even getest. We zitten nu in het jaar 2005 (29-11). Als iemand in de database staat met een geboortedatum `2001-01-28`, ruim binnen vandaag en (bijvoorbeeld-) 100 dagen, dan wordt die persoon niet geselecteerd. Dit gaat fout omdat het jaar van de maximale datum hoger is dan het jaar van vandaag.

[ Voor 3% gewijzigd door Verwijderd op 29-11-2005 15:31 ]


  • lier
  • Registratie: Januari 2004
  • Laatst online: 22-04 20:54

lier

MikroTik nerd

In MsSQL bestaat de DateDiff functie (welke waarschijnlijk geen ANSI SQL IS ?) Misschien bestaat in MySQL een equivalent voor deze functie ?

Eerst het probleem, dan de oplossing


Verwijderd

Topicstarter
lier schreef op dinsdag 29 november 2005 @ 15:34:
In MsSQL bestaat de DateDiff functie (welke waarschijnlijk geen ANSI SQL IS ?) Misschien bestaat in MySQL een equivalent voor deze functie ?
Deze functie, datediff(datum #1, datum #2), bestaat ook in MySQL. Hij geeft het aantal dagen verschil terug tussen datum #1 en datum #2. Maar hoe zou ik deze functie nutting kunnen gebruiken?

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Kun je niet van geboortedatum, verjaardag maken via een functie (dus niet in de database). Dan kun je namelijk DateDiff gebruiken:

Je pakt de dag en maand van de geboortedatum en zet als jaar het huidige jaar er bij (dan heb je dus de verjaardag), is de dag en maand al geweest dan moet je het huidige jaar + 1 gebruiken. vervolgens gebruik je DateDiff met de huidige datum en kijkt of deze minder dan x aantal dagen terug geeft.

[ Voor 11% gewijzigd door jelmervos op 29-11-2005 15:41 ]

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • P_de_B
  • Registratie: Juli 2003
  • Niet online
Je moet gewoon kijken dat het verschil in dagen tussen vandaag en de geboortedatum tussen 0 en 30 ligt

WHERE datediff (now(), geboortedatum) between 0 and 30

volgens mij werkt de mysql datadiff functie die hierboven staat standaard met dagen


edit: ik ben een eikel 8)7

[ Voor 8% gewijzigd door P_de_B op 29-11-2005 15:56 ]

Oops! Google Chrome could not find www.rijks%20museum.nl


Verwijderd

Topicstarter
Kaassoevlee schreef op dinsdag 29 november 2005 @ 15:40:
Kun je niet van geboortedatum, verjaardag maken via een functie (dus niet in de database). Dan kun je namelijk DateDiff gebruiken:

Je pakt de dag en maand van de geboortedatum en zet als jaar het huidige jaar er bij (dan heb je dus de verjaardag), vervolgens gebruik je DateDiff met de huidige datum en kijkt of deze minder dan x aantal dagen terug geeft.
Het is vandaag 29-11-2005. Stel, iemand is binnenkort jarig, en wel op 01-01-2006. Volgens jouw theorie wordt zijn verjaardag 01-01-2005 (vervang het jaar uit zijn geboortedatum door het huidige jaar). Het verschil tussen vandaag en de nieuwe datum is groter dan het échter verschil en dus wordt de persoon niet geselecteerd.
P_de_B schreef op dinsdag 29 november 2005 @ 15:42:
Je moet gewoon kijken dat het verschil in dagen tussen vandaag en de geboortedatum tussen 0 en 30 ligt

WHERE datediff (now(), geboortedatum) between 0 and 30

volgens mij werkt de mysql datadiff functie die hierboven staat standaard met dagen
Voorbeeld;
Ik ben in december jarig, en ik ben geboren in 1976. Het verschil in dagen tussen vandaag en mijn geboortedatum is dan (veel) groter dan 30 natuurlijk. Deze (gedachten-)fout maaktte ik in het begin ook.

[ Voor 27% gewijzigd door Verwijderd op 29-11-2005 15:45 ]


  • Maasluip
  • Registratie: April 2002
  • Laatst online: 22-04 15:59

Maasluip

Kabbelend watertje

kenneth schreef op dinsdag 29 november 2005 @ 15:25:
Dat gaat volgens mij vanaf 1 november fout ...
Ja, klopt. Had ik even niet bij stilgestaan. Maar anderen hebben meer MySQL kennis om dat in de details op te lossen.

Signatures zijn voor boomers.


  • L-VIS
  • Registratie: April 2005
  • Nu online
Misschien niet jouw oplossing, maar ik snap niet waarom je van de datum geen domein tabel hebt gemaakt. Je geeft dan elke dag een unieke opvolgend nummer en kunt daardoor heel makkelijk er 100 dagen bijtellen. 31-12-2005 is 365, 01-01-2006 is 366.

Een ander groot voordeel is dat je hierdoor meer specifieke informatie over een bepaalde dag kan opslaan.


Edit: Sorry ik zit ff te slapen, dit heeft niks met jouw probleem te maken.

[ Voor 11% gewijzigd door L-VIS op 29-11-2005 15:56 . Reden: Slaperigheid ]


  • _js_
  • Registratie: Oktober 2002
  • Laatst online: 13-01 07:19
BeginVanPeriode is de eerste dag van de periode waarin je verjaardagen zoekt
EindVanPeriode is de laatste dag van de periode waarin je verjaardagen zoekt
Verjaardag is het veld met geboortedatum in je database
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
WHERE
(
  (DAYOFMONTH(BeginVanPeriode) >= DAYOFMONTH(Verjaardag) AND MONTH(BeginVanPeriode) = MONTH(Verjaardag))
  OR
  (MONTH(BeginVanPeriode) > MONTH(Verjaardag))
)
AND
(
  (DAYOFMONTH(EindVanPeriode) <= DAYOFMONTH(Verjaardag) AND MONTH(EindVanPeriode) = MONTH(Verjaardag))
  OR
  (MONTH(EindVanPeriode) < MONTH(Verjaardag))
)

  • kenneth
  • Registratie: September 2001
  • Niet online

kenneth

achter de duinen

L-VIS schreef op dinsdag 29 november 2005 @ 15:53:
Misschien niet jouw oplossing, maar ik snap niet waarom je van de datum geen domein tabel hebt gemaakt. Je geeft dan elke dag een unieke opvolgend nummer en kunt daardoor heel makkelijk er 100 dagen bijtellen. 31-12-2005 is 365, 01-01-2006 is 366.

Een ander groot voordeel is dat je hierdoor meer specifieke informatie over een bepaalde dag kan opslaan.


Edit: Sorry ik zit ff te slapen, dit heeft niks met jouw probleem te maken.
Sowieso snap ik niet waarom je dat zou willen, lijkt me een beetje ranzig om in een tabel berekende waarden op te slaan. Een datum IS een uniek opvolgend nummer, zij het in een raar formaat.

Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.


  • L-VIS
  • Registratie: April 2005
  • Nu online
Tja normaal gesproken is het ook ranzig. Maar er zijn wel situaties te bedenken wanneer je dat wilt. Ik denk bijvoorbeeld aan vakanties, als je die zou willen bijhouden.

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 09:01
Als begindatum en begindatum in het zelfde jaar liggen moet je selecteren tussen deze datums,
anders moet je selecteren van begin datum tot het einde van het jaar en van begin van het jaar tot de einddatum.
In SQL kom ik dan op zoiets, wat wss nog wel te optimaliseren is:
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SELECT  voornaam,
    DATE_FORMAT(geboortedatum, "%m-%d")
FROM nawdata
WHERE    //zelfde jaar
    ( DATE_FORMAT(NOW(), "%y") = DATE_FORMAT(NOW()+60, "%y")
      AND DATE_FORMAT(geboortedatum, "%m-%d") between DATE_FORMAT(NOW(), "%m-%d") and DATE_FORMAT(NOW()+60, "%m-%d")
    )

    //ongelijk jaar
    OR ( DATE_FORMAT(NOW(), "%y") <> DATE_FORMAT(NOW()+60, "%y")
        AND (
            (DATE_FORMAT(geboortedatum, "%m-%d") > DATE_FORMAT(NOW(),"%m-%d") 
            OR
            (DATE_FORMAT(geboortedatum, "%m-%d") < DATE_FORMAT(NOW()+60,"%m-%d")
        )
    )

[ Voor 26% gewijzigd door T-MOB op 29-11-2005 16:27 ]

Regeren is vooruitschuiven


  • LuCarD
  • Registratie: Januari 2000
  • Niet online

LuCarD

Certified BUFH

Misschien zoiets?

SQL:
1
2
3
4
5
6
SELECT voornaam,
       DATE_FORMAT(geboortedatum, "%m-%d")
FROM nawdata  
WHERE
       YEAR( FROM_DAYS(TO_DAYS(DATE_ADD(NOW() INTERVAL 30 DAYS) - TO_DAYS(geboortedatum)) )
       != YEAR( FROM_DAYS(TO_DAYS(NOW())-TO_DAYS(geboortedatum)) )


niet getest....

Programmer - an organism that turns coffee into software.


Verwijderd

Topicstarter
Ik ben er na lang puzzelen uitgekomen en ik weet zeker, ook gezien de vele topics die ik heb bekeken, dat er veel vraag is - en komt - naar de volgende query/gedachtengang:

MySQL query om aankomende verjaardagen te selecteren:

code:
1
2
3
4
5
6
7
8
9
SELECT
voornaam,
geboortedatum
FROM nawdata
WHERE
DATE_FORMAT(DATE_ADD(geboortedatum, INTERVAL CEILING((TO_DAYS(CURDATE())-TO_DAYS(geboortedatum)-1)/365.25) YEAR), "%Y-%m-%d")
BETWEEN
DATE_FORMAT(NOW(), "%Y-%m-%d") AND 
DATE_FORMAT(NOW() + INTERVAL 60 DAY, "%Y-%m-%d")


Uitleg
Regel 6:
Hier wordt de persoon zijn eerstvolgende verjaardag gemaakt.
1. Hoe krijg je iemand zijn eerstvolgende verjaardag?
Tel [zijn huidige leeftijd + 1] op bij zijn geboortejaar.

2. Hoe krijg je iemand zijn leeftijd aan de hand van een geboortedatum?
Tel het [aantal dagen vanaf het jaar 0 tot vandaag] en [het aantal dagen vanaf het jaar 0 tot aan de eerstvolgende verjaardag]. Trek deze van elkaar af, en deel het resultaat door [aantal dagen in een jaar; 365,25 dus]. Dit is de enigste smet op de query, dat deze deling (.25) niet supernauwkeurig is (als iemand daar nog een aanvulling op heeft, graag). De deling met het kwart wordt vanzelfsprekend gedaan omdat er binnen 4 jaar (1 jaar is dus 0.25) één schrikkeljaar is.

De dagen vanaf het jaar 0 totaan datum X krijg je door gebruik te maken van de functie TO_DAYS(). Met behulp van de deling (het resultaat is dus iemand zijn leeftijd) en de functie CEILING() (afronden naar boven) krijgen we dus [de leeftijd + 1 jaar]. En die zochten we. Dit hele gebeuren zetten we in de functie DATE_FORMAT om een mooie datum (yyyy-mm-dd) terug te krijgen.

[Eerstvolgende verjaardag] is gevonden:
code:
1
DATE_FORMAT(DATE_ADD(geboortedatum, INTERVAL CEILING((TO_DAYS(CURDATE())-TO_DAYS(geboortedatum)-1)/365.25) YEAR), "%Y-%m-%d")


Met dit gegeven kunnen we gemakkelijk de data uit de tabel selecteren van personen die binnen nu en een x-aantal dagen jarig zijn. We doen dit met BETWEEN, waarbij de eerste navolgende waarde vandaag is en de tweede waarde de datum over x-aantal dagen.

Voila.

/me geeft zichzelf een schouderklopje.

offtopic:
Wellicht is de uitleg niet helemaal helder, maar het werkt als een tiet. Had geen zin om een betere uitleg te typen, wil namelijk snel verder met de applicatie...


Nb; de -1 na TO_DAYS(geboortedatum) geeft aan of verjaardagen van vandaag meegenomen moeten worden in het resultaat. Als je de -1 weglaat, worden verjaardagen vanaf (zonder vandaag, met-) morgen geselecteerd.

[ Voor 12% gewijzigd door Verwijderd op 29-11-2005 16:52 ]


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
ik zou het zoiets doen. ( Is in T-SQL maar je kan de datum berekeningen natuurlijk ook gewoon in de query of je script opnemen ).

SQL:
1
2
3
4
5
6
7
8
9
10
DECLARE @startdate DATETIME
DECLARE @enddate DATETIME

SET @startdate = GETDATE()
SET @enddate = DATEADD( day, 30, @startdate )

SELECT  naam
FROM    verjaardagen
WHERE   MONTH( geboortedatum ) BETWEEN MONTH( @startdate ) AND MONTH( @enddate )
AND DAY( geboortedatum ) BETWEEN DAY( @startdate ) AND DAY( @enddate )

[ Voor 32% gewijzigd door Woy op 29-11-2005 16:55 . Reden: even between gebruikt in de code ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Verwijderd

Topicstarter
rwb schreef op dinsdag 29 november 2005 @ 16:52:
ik zou het zoiets doen. ( Is in T-SQL maar je kan de datum berekeningen natuurlijk ook gewoon in de query of je script opnemen ).

SQL:
1
2
3
4
5
6
7
8
9
10
DECLARE @startdate DATETIME
DECLARE @enddate DATETIME

SET @startdate = GETDATE()
SET @enddate = DATEADD( day, 30, @startdate )

SELECT  naam
FROM    verjaardagen
WHERE   MONTH( geboortedatum ) BETWEEN MONTH( @startdate ) AND MONTH( @enddate )
AND DAY( geboortedatum ) BETWEEN DAY( @startdate ) AND DAY( @enddate )
Weet niet of het werkt, maar werkt sowieso níet als je data wilt selecteren over een periode die langer duurt dan een jaar. Kijk maar;

startdate = 29 november 2005
enddate = 1 februari 2007
Karel Appel, geboortedatum = 3 maart 1970

Karel Appel zal met jouw query niet geselecteerd worden, want hij loopt vast op de voorwaarde [b]maand-geboortedatum(maart) BETWEEN maand_startdate(november) AND maand-enddate(februari).

Zonder te willen patsen is de door mijzelf gevonden query dus meer universeel te gebruiken.

Verwijderd

29-feb-1976?

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 09:01
Dat is een schrikkeldag, 29 februari 2006 bestaat niet en kan dus ook niet als eerstvolgende verjaardag worden aangemerkt.

Regeren is vooruitschuiven


  • Stamgastje
  • Registratie: April 2003
  • Laatst online: 02-02-2020
Zo doe ik het (MySQL 4+):

SQL:
1
2
3
4
SELECT `Geboortedatum`,
CONCAT(IF(RIGHT(CURDATE(), 5) > RIGHT(`Geboortedatum`, 5), YEAR(CURDATE()) + 1, YEAR(CURDATE())), RIGHT(`Geboortedatum`, 6)) AS `Verjaardag`
(YEAR(CURDATE())-YEAR(`Geboortedatum`)) - (RIGHT(CURDATE(), 5) <= RIGHT(`Geboortedatum`, 5)) + 1 AS `Leeftijd`
FROM `<tabel-naam>`


Het enige wat je nog even moet toevoegen is een "WHERE `Verjaardag` BETWEEN ..." om de data tussen nu en 30 dagen eruit te halen.

[ Voor 33% gewijzigd door Stamgastje op 29-11-2005 21:54 ]


  • P_de_B
  • Registratie: Juli 2003
  • Niet online
Het is lastiger dan het in eerste instantie lijkt, maar voor SQL Server is dit een werkende oplossing:

SQL:
1
2
3
 WHERE
  DATEDIFF(d, GETDATE(), DATEADD(yy, (DATEDIFF(yy, geboortedatum, GETDATE()) 
  + CASE WHEN DATEADD(yy, DATEDIFF(yy, geboortedatum, GETDATE()), geboortedatum) >= GETDATE() THEN 0 ELSE 1  END), geboortedatum)) BETWEEN 0 AND 30


Bron

Oops! Google Chrome could not find www.rijks%20museum.nl

Pagina: 1