PHP Problem mit Geburtstagsabfrage

B

+ BELA B. +

Gast
Hi,
ich stehe vor einem problem...

und zwar, habe ich in der MySQL Datenbank eine Tabelle "spieler".
diese haben ein Feld das heißt "gebDate" (INT)
dort wird der Geburtstag des jeweiligen Spielers gespeichert in Form eines UNIX Timestamps.

Jetzt möchte ich etwas bauen, damit ich ausgeben kann WER Heute Geburtstag hat...

Wie funktioniert hier die SQL Abfrage? ICh hab ehrlich gesagt im moment keinen Plan,

Den so funktionierts nicht:

$startDate = mktime(0,0,0);
$endDate = mktime(0,0,0,date('n'),date('d')+1);

Und dann eine Abfrage "WHERE gebDate zwischen $startDate und $endDate...

Bitte um dringende Hilfe....

mfg tom
 
du brauchst nur nen and ;)
PHP:
SELECT Name WHERE gebDate >'$startDate' AND gebDate<'$endDate' SORT BY Name Desc

hoffe mal, das stimmt jetzt - das letzte mal das ich mit php/sql gearbeitet hab ist etwas her^^
 
Hallo + BELA B. +
PHP:
SELECT Name 
WHERE gebDate = current_date()
 
Zuletzt bearbeitet:
Was wird denn für ein Fehler gebracht?

Funktioniert so ein Datenvergleich wirklich, wenn das Datum in der DB als INT gespeichert ist?
SQL bietet doch einen eigenen Datentyp dafür an, oder?
 
wie jetzt genau?

@keepExtreme das kann ja net funktionieren?
weil man beachte die jahrgänge ;)

@knoxyz
Wie meinst? was bringt das?
 
Funktioniert nicht ganz...

liefert mit NULL:
$res = $db->query("SELECT * FROM `po_tus_ardning_spieler` WHERE `gebDate` BETWEEN UNIX_TIMESTAMP(CURDATE()) AND (UNIX_TIMESTAMP(CURDATE()) + 86400 - 1)");
var_dump($res);
 
es ist quark hier irgendwas mit between zu benutzen
du willst ein tag bestimmen daher kannst du einfach auf tag
ebene arbeiten ...
 
+ BELA B. + schrieb:
Funktioniert nicht ganz...
hatt den überhaupt heute jemand Geburtstag? ;)
denn die Bedingung funktioniert garantiert:
Code:
SELECT UNIX_TIMESTAMP() BETWEEN UNIX_TIMESTAMP(CURDATE()) AND (UNIX_TIMESTAMP(CURDATE()) + 86400 - 1)


AlbertLast schrieb:
es ist quark hier irgendwas mit between zu benutzen
du willst ein tag bestimmen daher kannst du einfach auf tag
ebene arbeiten ...
ne, dein Query ist Quark, du wandelst einen Unix-Timestamp in ein Datum um, damit es dann verglichen werden kann, dadurch verlierst du aber die Möglichkeit einen Index, der auf gebDate liegt zu nutzen (der existieren sollte).
Ergo führt dein Query zu einem Fulltable-Scan und wird jeden Eintrag der Tabelle von der Platte laden.
 
@+ BELA B. +
Der Zweizeiler von soll natürlich nicht in die Where-Klausel,
sondern ist bereits die vollständige Abfrage.

Da du ein UNIX-Timestamps benutzt (was versprichst du dir davon, insb. wenn nur ein Datum gespeichert werden soll???)
ist die Ergänzung von AlbertLast in #5 richtig und am verständlichsten.

@ice-breaker
Deine Aussage ist Quark!
Es kann immer ein Index erstellt werden, der Zieldatentyp spielt keine Rolle.
Du hättest stattdessen den Unix-Timestamp zum Speichern eines Datums in Frage stellen sollen...
 
Zuletzt bearbeitet:
knoxyz schrieb:
@ice-breaker
Deine Aussage ist Quark!
Es kann immer ein Index erstellt werden, der Zieldatentyp spielt keine Rolle.
Du hättest stattdessen den Unix-Timestamp zum Speichern eines Datums in Frage stellen sollen...

Ich optimiere schon sehr lange MySQL-Datentypen, sei dir sicher, dass ich keinen Quark erzähle.
Ja du kannst immer einen Index erstellen, indem AlbertLast jedoch eine Funktion auf die Spalte der Tabelle anwendet (Transformation) kann der Index nicht mehr zur Beschleunigung der Abfrage eingesetzt werden, wie er eigentlich gedacht ist.
Das beste, was MySQL noch herausholen kann, ist, dass die Funktion iterativ auf jeden Wert des Indexes angewendet wird, das nennt sich dann Index-Scan.
Du kannst gerne sein und mein Beispiel mit einem EXPLAIN-Statement und mk-query-profiler (maatkit) vergleichen, und du wirst feststellen, dass der Index mit seinem Statement nicht effizient genutzt werden kann.
Bei einer Tabelle mit n Datensätzen und m Results werden bei ihm n Datensätze (vllt auch nur Index-Einträge) geprüft, bei meiner Lösung wird dies bei m liegen.
 
ice-breaker schrieb:
Ich optimiere schon sehr lange MySQL-Datentypen...
Soll ich das nun gut oder schlecht finden?!
Vermutlich letzteres wenn nicht nichtmal auf den geeignetsten Datentypen geachtet wird
(hier zweifellos nicht UNIX-Timestamp, sondern date).
 
Die Frage ist doch: kann auch bei einem Datentyp DATE auch nach Tag und Monat via Index gesucht werden (ohne Index-Scan). Denn nur diese Komponenten des Datums sind für die gegenwärte Problemstellung ausschlaggebend.

Bei wenigen Benutzern ist der Index sicher noch nicht SO wichtig.
Sollte die Benutzerzahl schnell steigen (Szenario: CRM System oder große Community), sollte überlegt werden, ob nicht zugunsten der Geschwindigkeit und entgegen der Redundanzvermeidung ein Extrafeld mit Index angelegt wird, das nur Monat und Tag enthält.
 
mir viel gerade auf das ich man das jahr abschneiden muss
irgendwie föllig vergessen ...

Code:
where FROM_UNIXTIME(gebDate,'%d-%m') = DATE_FORMAT(CURDATE(),'%d-%m');
 
knoxyz schrieb:
Vermutlich letzteres wenn nicht nichtmal auf den geeignetsten Datentypen geachtet wird
(hier zweifellos nicht UNIX-Timestamp, sondern date).
Ob ein Unixtimestamp gespeichert wird oder der native Date-Datentyp ist eine persönliche Entscheidung, die kann man nicht für andere treffen.
Ich persönlich präferiere auch den date-Datentyp kann aber auch jeden Entwickler verstehen, der normale Unixtimestamp lieber nutzt weil die Interaktion simple ist, beim Speichern in die Datenbank muss nicht in ein Date umgewandelt werden und beim Lesen nicht zurück in einen Unixtimestamp.
Solch eine Argumentation ist echt lächerlich :rolleyes:
Aber neija ich kenne das, wird einem die falsche Behauptung von vorher wiederlegt sucht man sich einfach den nächsten Punkt :rolleyes:

XunnD schrieb:
Die Frage ist doch: kann auch bei einem Datentyp DATE auch nach Tag und Monat via Index gesucht werden (ohne Index-Scan). Denn nur diese Komponenten des Datums sind für die gegenwärte Problemstellung ausschlaggebend.
die Ansätze mit schneide ab, oder wandele um funktionieren nie ohne Index-Scan.
Der Between-Ansatz funktioniert mit jedem Datentyp ohne Index-Scan mit effizientem B-Baum-Zugriff.


XunnD schrieb:
Sollte die Benutzerzahl schnell steigen (Szenario: CRM System oder große Community), sollte überlegt werden, ob nicht zugunsten der Geschwindigkeit und entgegen der Redundanzvermeidung ein Extrafeld mit Index angelegt wird, das nur Monat und Tag enthält.
der Between-Ansatz ist "Lightning Fast", nur Monat und Tag wird dich auch nicht großartig weiterbringen.
Wenn ein Datensatz über eine B(+)-Baum-Suche gefunden werden kann, ist der Query effizient, vllt als billigstes Maß.
Da hängen aber noch hundert weitere Bedinungen wie Subquerys, temporäre Tabellen, Foreign-Key-Checks und und und und dran.
 
Klar gibt es ein Argument gegen Unixtimestamp, besonders zusammen mit Geburtstagen. Bei Personen die vor 1970 geboren sind erhalten wir negative Zahlen und am 19. Januar 2038 ist Sense auf allen 32-Bit-Systemen. ;)
 
@icebreaker:

Mir ist sehr wohl klar, dass BETWEEN auf den Index zugreift und das "blitzschnell" ist. Nur bringt uns das in unserem Szenario nicht weiter, da NICHT nur EIN Datums-Bereich gefunden werden soll, sondern ALLE.


Hier sind die Geburtstage vom 06.09. der letzten fünf Jahre (plus UNIX-Timestamp):
2010-09-06 (1283724000)
2008-09-06 (1252188000)
2007-09-06 (1220652000)
2006-09-06 (1189029600)
2005-09-06 (1125957600)

Jetzt sollte der Standpunkt langsam klar werden: entweder Jahr abschneiden (und das dann Query für Query tun - bei wenigen Datensätzen) oder den Geburtstag bereits so abspeichern: MONAT/TAG (bei zu vielen Datensätzen - um DANN den Index nutzen zu können).
 
Hi,

ich hab das problem immer noch nicht gelöst,
was muss ich nun als query angeben?

$res = $db->query("QUERY???");

lg und danke jungs!
 
Den gegebenen Rahmenbedingungen entsprechend würde ich folgenden Query verwenden, wie bereits von ice-breaker geschrieben wurde.

PHP:
$res = $query('SELECT * FROM relation WHERE gebDate BETWEEN UNIX_TIMESTAMP(CURDATE()) AND (UNIX_TIMESTAMP(CURDATE()) + 86400 - 1) SORT BY tupel DESC');
 
Zurück
Oben