Hallo alle miteinander,
Ich möchte für eine Statistik verschiedene Altersbereiche der Benutzer
meiner Anwendung auswerten (also so etwas wie "Jungen, 13-17 Jahre" usw.
Mein bisheriger Code schaut so aus (Abfrage aus PHP):
1
2
AND User.Geburtstag BETWEEN DATE_SUB(NOW(),INTERVAL ".$To." YEAR)
3
AND DATE_SUB(NOW(),INTERVAL ".$From." YEAR)
Dabei wäre jetzt $From eben die 13 und $To die 17.
Ich habe mittlerweile festgestellt, dass da was nicht sitmmt, weil so
einige Leute durch das "Raster" fallen und nirgens auftauchen, bin
jedoch zu noch keiner funktionierenden Lösung gekommen.
Ich hatte schon die Idee, dass man ja 1 Jahr lang sein Alter hat und 363
Tage addiert bzw abgezogen, aber das war auch nicht richtig (oder ich
hatte einen Fehler in meiner Query.
Ich weiss dass es eigentlich Pipieinfach sein müsste, aber ich stehe
gerade so dermassen auf dem Schlauch und drehe mich im Kreis, dass es
mein Hirn total blockiert.
Würde mich über ein wenig Input freuen, damit ich das Modul dieses WE
noch fertig stellen kann.
Hoffe es findet sich jemand der mir hilft.
Vielen Dank!
Hi,
die MySQL-Referenz hat schon was auf dem silbernen Tablett:
https://dev.mysql.com/doc/refman/5.0/en/date-calculations.html
... WHERE TIMESTAMPDIFF(YEAR, User.Geburtstag, CURDATE()) BETWEEN ? AND
?
achja: packe nie und nimmer Parameter für SQL-Statements direkt in
Statements!
Verwende Platzhalter (hier: ?) und arbeite mit Prepare.
Viele Grüße
Chris
Vielen Dank für die Antwort, werde mir das mal genauer anschauen. Wieso
sollte man die Parameter nicht ins State schreiben ( habe vorher
natürlich die Daten validiert)
Ok, was hier natürlich in meinem Codeschnipsel nicht ersichtlich ist:
Bei mir gehen nur Daten in die Query, die vorher mit
mysqli_real_escap_string oder intval() "gecheckt" wurden. Trotzdem
schlecht?
Wenn das jetzt nich für Tage genau gelten sollte sondern nur für das
Ganze Jahr.. so das die statistik wenn morgen jemand Geburtstag hätte
nicht wieder anders aussieht.
Könnte fixer als Between sein.
Ungeprüft:
WHERE YEAR(GEBURTSTAG) < YEAR(CURDATE())-ALTERMIN AND YEAR(GEBURTSTAG)
>YEAR(CURDATE())-ALTERMAX
Ich habe es jetzt mit der weiter oben genannten Abfrage (mit Between)
gelöst, das ist auch ausreichend performant bei um die 100 Benutzern.
Vielen dank an alle für die Tipps und Hinweise!
Jens Plappert schrieb:> Bei mir gehen nur Daten in die Query, die vorher mit> mysqli_real_escap_string oder intval() "gecheckt" wurden. Trotzdem> schlecht?
wenn ich mich richtig erinnere, gab es auch mit den Escape-Methoden
mögliche Injections.
Nimm einfach Prepared statements, damit bist du garantiert auf der
sicheren Seite und das Statement muss bei mehreren gleichartigen
Abfragen (z.B. mehrere Altersgruppen) nur einmal kompiliert werden.
Mich hat das weil es pratisch ist nicht in ruhe gelassen und habe mir
das nochmal angeschaut,als Anhang mal eine Idee für einen automatischen
3 Jahres Interval auf die ganze Tabelle ohne WHERE automatisch sortiert.
Bedarf noch einer Ergebnisprüfung, sieht schonmal gut aus.
SELECT COUNT(*) AS ANZAHL ,(YEAR(NOW())-YEAR(MIN(user_birthdate)))AS
ALTERjahr,YEAR(MIN(user_birthdate))AS VON,YEAR(MAX(user_birthdate))AS
BIS, ROUND(YEAR(user_BIRTHDATE)/3) AS jahresindex FROM `users` GROUP By
jahresindex
Die Variante mit dem 'TIMESTAMPDIFF' führt leider zu einem 'full table
scan'. Bei 100 Eintägen mag das noch kein Problem sein, wenn es mal mehr
werden schon.
Hab grad kein MySQL zum testen da, aber die Ursprungsvariante könnte an
einem falschen Datentyp scheitern. Eventuell reicht es NOW() jeweils
durch CURDATE() zu ersetzen. Ansonsten um den Aufruf von DATE_SUB() noch
ein CAST() auf den für das Feld User.Geburtstag verwendeten Datentyp.
Jens Plappert schrieb:> Bei mir gehen nur Daten in die Query, die vorher mit> mysqli_real_escap_string oder intval() "gecheckt" wurden. Trotzdem> schlecht?
Das bringt dir an der Stelle kaum was, weil du ja nichtmal
Anführungszeichen um den Wert drum hast. Benutz' prepared statements.
Hallo Jens,
Jens Plappert schrieb:> Ich möchte für eine Statistik verschiedene Altersbereiche der Benutzer> meiner Anwendung auswerten (also so etwas wie "Jungen, 13-17 Jahre" usw.>> Mein bisheriger Code schaut so aus (Abfrage aus PHP):>>
1
> AND User.Geburtstag BETWEEN DATE_SUB(NOW(),INTERVAL ".$To." YEAR)
2
> AND DATE_SUB(NOW(),INTERVAL ".$From." YEAR)
3
>
>> Dabei wäre jetzt $From eben die 13 und $To die 17.> Ich habe mittlerweile festgestellt, dass da was nicht sitmmt, weil so> einige Leute durch das "Raster" fallen und nirgens auftauchen, bin> jedoch zu noch keiner funktionierenden Lösung gekommen.
Möglicherweise ist es bei MySQL nicht so, aber bei anderen DBMS muß der
erste Parameter für BETWEEN unbedingt vor dem zweiten liegen.
HTH,
Karl