Datumsdifferenz berechnen
Ute
- php
Hallo an alle, habe folgendes Problem oder einfach nur einen Klemmer.
Ich habe in einer Datenbank ein Feld (datum1) mit einem Datumswert; d.h. jedem User ist ein bestimmtes Datum zugeordnet. (bspw. ein Anmeldedatum) Wie kann ich jetzt berechnen wie viele Tage seit dem Datum (datum1) bis heute vergangen sind? Ich kenne zwar die Funktion datediff, komme aber damit nicht klar. Ich möchte eine Liste ausgeben, wo neben dem Namen die Differenz auftaucht. Danke schon mal für eure Hilfe.
Hi,
Ich kenne zwar die Funktion datediff, komme aber damit nicht klar.
"Ich kann zwar reden, aber mich nicht verständlich ausdrücken."
MfG ChrisB
Hi,
»» Ich kenne zwar die Funktion datediff, komme aber damit nicht klar.
"Ich kann zwar reden, aber mich nicht verständlich ausdrücken."
MfG ChrisB
Hallo ChrisB, du hast sicher recht, ich habe mich "verdrückt ausgekehrt" Ich bitte um Entschuldigung. Vg Ute
Hello,
Du kannst die Datenbank rechnen lassen, oder, da Du es sowieso anzeigen lassen willst, auch von der API (PHP) ausrechnen lassen.
siehe: https://forum.selfhtml.org/?t=185456&m=1230757
Es sollten nur beide Werte, also der für den Datensatz und der für die Vergleichszeit, aus der DB-Abfrage kommen.
Liebe Grüße aus dem Cyberspace
Tom vom Berg
Es sollten nur beide Werte, also der für den Datensatz und der für die Vergleichszeit, aus der DB-Abfrage kommen.
Hallo Tom, danke für deine Antwort, das werde ich mal ausprobieren und mich wieder melden. VG Ute
Hallo,
Hallo an alle, habe folgendes Problem oder einfach nur einen Klemmer.
vermutlich letzeres.
Wie kann ich jetzt berechnen wie viele Tage seit dem Datum (datum1) bis heute vergangen sind? Ich kenne zwar die Funktion datediff,
genau mit dieser Funktion. Schließlich liefert sie Dir (in Verbindung mit CURRENT_DATE) genau das zurück, was Du haben möchtest. [1]
komme aber damit nicht klar.
Was bedeutet das? Was hast Du versucht, woran bist Du gescheitert?
Freundliche Grüße
Vinzenz
[1] Es sei denn, Du möchtest den Zeitanteil des Datums mit berücksichtigen. CURRENT_TIME und TIME könnten Dir in diesem Fall helfen (zusätzlich zu DATEDIFF). Ach ja, was zum Kontrollfluss benötigtest Du ebenfalls.
Danke erstmal für eure Reaktion. Also ich hole mir aus 2 verschiedenen Tabellen Daten. In der einen Tabelle findet man den Namen in der anderen das Datum. Verknüpft sind beide Tabellen über die ID. Ich habe mir mit Hilfe einer while-Schleife die ID, den Namen und das Datum (datum1) (als Liste)ausgeben lassen.
so in etwa:
$i =0;
while ($i<$number) {
$row = mysql_fetch_array($result);
$name = $row["name"];
$nummer = $row["id"];
$adat = $row["datum1"];
print "$id, $name, $datum1<br>";
$i++;
}
Wie bekomme ich jetzt neben das Datum (datum1) auf jeder Zeile das zweite Datum, also die Differenz aus heute ./. datum1 ? Ich haatte die datediff-Funktion mit in die Schleife bauen wollen, aber da bekam ich jedesmal eine Syntaxfehlermeldung. Danke.
Hallo,
Danke erstmal für eure Reaktion. Also ich hole mir aus 2 verschiedenen Tabellen Daten. In der einen Tabelle findet man den Namen in der anderen das Datum. Verknüpft sind beide Tabellen über die ID.
die DATEDIFF-Funktion musst Du in Dein SQL-Statement einbauen, wenn PHP das Ergebnis abarbeitet, ist es zu spät. Daher wäre es eine gute Idee, statt des verarbeitenden PHP-Codes das SQL-Statement zu zeigen.
Freundliche Grüße
Vinzenz
die DATEDIFF-Funktion musst Du in Dein SQL-Statement einbauen, wenn PHP das Ergebnis abarbeitet, ist es zu spät. Daher wäre es eine gute Idee, statt des verarbeitenden PHP-Codes das SQL-Statement zu zeigen.
Hallo Vinzenz hier ist die Abfrage:
$query="select * from users, data where users.userid=data.userid" ;
Wenn ich dich richtig verstanden habe, muss in diese also die datediff mit rein? Oder macht dann eine neue Abfrage? z. B.
$query2="select datediff($datum1,getdate())"; ???
Vielen Dank für deine Mühen, ich glaube, ich stehe irgendwie auf der Leitung ;-) Vg Ute
Hallo Ute,
» die DATEDIFF-Funktion musst Du in Dein SQL-Statement einbauen, wenn PHP das Ergebnis abarbeitet, ist es zu spät. Daher wäre es eine gute Idee, statt des verarbeitenden PHP-Codes das SQL-Statement zu zeigen.
$query="select * from users, data where users.userid=data.userid" ;
es ist eine gute Idee, SQL-Schlüsselworte groß zu schreiben, die Syntaxhervorhebung des Forums zu nutzen und explizite Joins statt implizite in der WHERE-Klausel zu schreiben.
SELECT
*
FROM
users
INNER JOIN
data
ON
users.userid = data.userid
Leider verrät mir SELECT * ...
nicht, wie Deine Datumsspalte heißt :-(
Wenn ich dich richtig verstanden habe, muss in diese also die datediff mit rein?
Ja:
SELECT
*,
[link:http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_datediff@title=DATEDIFF](
[link:http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_curdate@title=CURDATE()], -- der erste Parameter muss der spätere Zeitpunkt sein
<deine_datumsspalte> -- natürlich nicht in spitze Klammern :-)
) tage -- ein netter Spaltenname; Du kannst in PHP somit
-- leichter auf diese Spalte zugreifen
FROM
users
INNER JOIN
data
ON
users.userid = data.userid
Wenn Du nicht alle Spalten beider Tabellen benötigst, ist es sinnvoll, die Spalten in der Spaltenliste einzeln aufzuführen.
Freundliche Grüße
Vinzenz
es ist eine gute Idee, SQL-Schlüsselworte groß zu schreiben, die Syntaxhervorhebung des Forums zu nutzen und explizite Joins statt implizite in der WHERE-Klausel zu schreiben.
Wenn Du nicht alle Spalten beider Tabellen benötigst, ist es sinnvoll, die Spalten in der Spaltenliste einzeln aufzuführen.
Freundliche Grüße
Vinzenz
Hallo Vinzenz, das sieht richtig gut aus und ich denke, so könnte es funktionieren; außerdem vielen lieben Dank für deine Hinweise. Man wird halt nie dümmer. Also nochmals danke. Ich melde mich, wie es ausgegangen ist.
VG und schöne Ostern Ute
Hallo Vinzenz, bin leider noch nicht mit der Sache klar gekommen. Die Abfrage an sich ist mir schon klar und die funktioniert so weit auch. Aber was was bedeutet das "tage" nach der Klammer und wie gebe ich die Differenz dann zeilenweise aus? Vielen Dank für deine Hilfe. Freundliche Grüße Ute
SELECT
*,
DATEDIFF(
CURDATE(), -- der erste Parameter muss der spätere Zeitpunkt sein
<deine_datumsspalte> -- natürlich nicht in spitze Klammern :-)
) tage -- ein netter Spaltenname; Du kannst in PHP somit
Hello,
Hallo Vinzenz, bin leider noch nicht mit der Sache klar gekommen. Die Abfrage an sich ist mir schon klar und die funktioniert so weit auch. Aber was was bedeutet das "tage" nach der Klammer und wie gebe ich die Differenz dann zeilenweise aus?
SELECT
*,
DATEDIFF(
CURDATE(), -- der erste Parameter muss der spätere Zeitpunkt sein
<deine_datumsspalte> -- natürlich nicht in spitze Klammern :-)
) tage -- ein netter Spaltenname; Du kannst in PHP somit
Das müsste ausgeschrieben 'as tage' heißen und ist der publizierte Name für die berechnete Spalte.
In deinem Resultset, dass Du von PHP aus erreichen kannst, steht also für die berechnete Spalte der Index ['tage'] im fetch_assoc()-Array.
Liebe Grüße aus dem Cyberspace
Tom vom Berg
»
Das müsste ausgeschrieben 'as tage' heißen und ist der publizierte Name für die berechnete Spalte.
In deinem Resultset, dass Du von PHP aus erreichen kannst, steht also für die berechnete Spalte der Index ['tage'] im fetch_assoc()-Array.
Hallo Tom, ja das macht Sinn mit dem "as tage". Nur ich bekomme das nicht Feld nicht ausgelesen. Hier mal die Ausgabe:
$i =0;
while ($i<$number) {
$row = mysql_fetch_assoc($result);
$name = $row["username"];
$nummer = $row["user_id"];
$adat = $row["pf_datum1"];
$rft = $row["tage"];
print "$name hat folgende Nummer: $nummer und ist seit dem $adat das sind $rft Tage angemeldet<br>";
$i++;
}
oder wäre $row = mysql_fetch_array($result); besser ? Funktionieren tun beide nicht. Also Name, ID, und Datum werden ausgegeben, aber dieses "Tage"-Feld eben nicht. Wo mache ich den Fehler? Danke. VG Ute
Mahlzeit Ute,
Wo mache ich den Fehler?
Wie sieht Deine Abfrage jetzt aus (sowohl PHP-, als auch SQL-Code)?
MfG,
EKKi
»
Wie sieht Deine Abfrage jetzt aus (sowohl PHP-, als auch SQL-Code)?
Hallo Ekki, hier ist die Abfrage, dabei hatte mir ja Vinzenz geholfen. Es werden alle Datensätze ausgegeben nur das Feld mit der Datumsdifferenz nicht. Deshalb vermute ich, dass da irgendwo noch ein Fehler ist.
$query = "SELECT
*,
DATEDIFF( CURDATE(),
pf_datum1
) as tage
FROM
users
INNER JOIN
data
ON
users.user_id=data.user_id";
Danke und VG Ute
Mahlzeit Ute,
Es werden alle Datensätze ausgegeben nur das Feld mit der Datumsdifferenz nicht.
Sehr merkwürdig. Hast Du mal versucht, die SQL-Syntax ein wenig zu verändern? Es kommt natürlich darauf an, welches DBMS in welcher Version Du nutzt.
In Oracle z.B. gibt's bei so unspezifischen * manchmal Probleme - insbesondere wenn NACH einem * noch weitere Felder aufgeführt werden. Probier doch mal aus, einfach die Reihenfolge der ausgewählten Felder zu ändern:
SELECT DATEDIFF(CURDATE(), pf_datum1) AS tage
, users.*
, data.*
FROM users
INNER JOIN data ON users.user_id=data.user_id
MfG,
EKKi
Hallo Ekki,
habe das * schon ersetzt und rufe nur noch die Felder ab, die ich benötige. Ich hatte noch eine andere Idee, aber da komme ich auch nicht weiter.
Und zwar: Kann es sein, dass es am Datumsformat liegt? CURDATE() liefert doch in YYYYMMDD und mein Datumsfeld zeigt: DD- M-YYYY an. Habe schon versucht zu formatieren, aber das habe ich einfach nicht hinbekommen. Danke und VG Ute
Mahlzeit Ute,
Und zwar: Kann es sein, dass es am Datumsformat liegt?
Eigentlich nicht. Ein Feld, das vom Feldtyp her ein Datumsfeld ist, sollte vom DBMS (Welches nutzt Du noch gleich? Habe ich das bisher übersehen oder hast Du es immer noch nicht genannt? Es spielt manchmal eine nicht unerhebliche Rolle, weswegen es auch immer angegeben werden sollte - das steht auch in der Charta und sogar im Formular, wenn man einen Beitrag erfasst) entsprechend genutzt werden können.
CURDATE() liefert doch in YYYYMMDD und mein Datumsfeld zeigt: DD- M-YYYY an.
Also nochmal: welches DBMS verwendest Du und welchen Feldtyp hat Deine Datumsspalte?
MfG,
EKKi
Mahlzeit Ute,
»» Und zwar: Kann es sein, dass es am Datumsformat liegt?
Eigentlich nicht. Ein Feld, das vom Feldtyp her ein Datumsfeld ist, sollte vom DBMS (Welches nutzt Du noch gleich? Habe ich das bisher übersehen oder hast Du es immer noch nicht genannt? Es spielt manchmal eine nicht unerhebliche Rolle, weswegen es auch immer angegeben werden sollte - das steht auch in der Charta und sogar im Formular, wenn man einen Beitrag erfasst) entsprechend genutzt werden können.
»» CURDATE() liefert doch in YYYYMMDD und mein Datumsfeld zeigt: DD- M-YYYY an.
Also nochmal: welches DBMS verwendest Du und welchen Feldtyp hat Deine Datumsspalte?
MfG,
EKKi
Hallo Ekki, ich glaube, jetzt kommen wir der Sache näher. Also erstmal Entschuldigung wegen der "überlesenen" Frage. Es ist Mysql 5.0 und das Feld hat den Typ varchar, Größe 10. Es ist eine Profilfeld in einem phpbb-Forum. Ich hatte das auch als Datumsfeld im Forum (über den admin-Bereich im Forum) angelegt; in Mysql wird es aber als varchar angezeigt. Einfach ändern über den phpmyadmin geht nicht. Danke und VG Ute
Mahlzeit Ute,
Es ist Mysql 5.0 und das Feld hat den Typ varchar, Größe 10.
Dann handelt es sich (für MySQL) nicht um ein Datumsfeld (und damit sind natürlich auch keine Datumsberechnungen mit dem enthaltenen Wert möglich), sondern lediglich um ein Feld mit Text als Inhalt. Ob da zufällig ein String, der wie ein Datum aussieht, "Rödelbödel", "17" oder nix drin steht, ist vollkommen egal.
Es ist eine Profilfeld in einem phpbb-Forum. Ich hatte das auch als Datumsfeld im Forum (über den admin-Bereich im Forum) angelegt;
Es ist relativ irrelevant, über welche Oberfläche Du ein Feld anlegst - solange diese Oberfläche anschließend Murks macht:
in Mysql wird es aber als varchar angezeigt.
Nein. Es wird nicht "als varchar angezeigt", es IST dann wohl ein einfaches VARCHAR-Feld. Dein Forum ist offenbar Mist.
Einfach ändern über den phpmyadmin geht nicht.
Warum nicht?
Dann kannst Du mit dem Feld auch keinerlei Datumsberechnungen durchführen. Was Du versuchen könntest ist, das Feld mittels der entsprechenden Funktion in ein Datum umzuwandeln ... dann könntest Du anschließend mit dem Ergebnis der Umwandlung auch Datumsberechnungen durchführen.
MfG,
EKKi
Hallo Tom und hallo Ekki, ihr habt mir sehr geholfen.
Es lag tatsächlich, wie schon vermutet, an diesem "varchar". Eigentlich logisch. Naja.
Also ich habe mir jetzt zu Testzwecken eine neue Tabelle angelegt, ein neues Feld (date) eingefügt und mal ein paar Daten manuell eingeben. Und siehe jetzt funktioniert auch die Berechnung mit datediff(). Bis dahin alles prima.
Nur ist es ja sehr mühselig, alle Daten von Hand zu ändern und mit der str-to-date kann ich nicht viel anfangen, weil ich nicht weiß, wie ich das umsetzen soll.
Könntet ihr mir bitte, bitte noch einmal dabei helfen, die entsprechende Abfrage dazu zu basteln?
Habt vielen Dank.
VG und schönes WE Ute
Hallo Ute,
Also ich habe mir jetzt zu Testzwecken eine neue Tabelle angelegt, ein neues Feld (date) eingefügt und mal ein paar Daten manuell eingeben. Und siehe jetzt funktioniert auch die Berechnung mit datediff(). Bis dahin alles prima.
Nur ist es ja sehr mühselig, alle Daten von Hand zu ändern und mit der str-to-date kann ich nicht viel anfangen, weil ich nicht weiß, wie ich das umsetzen soll.
nun dafür gibt es die UPDATE-Anweisung.
CURDATE() liefert doch in YYYYMMDD und mein Datumsfeld zeigt: DD- M-YYYY
hmm wirklich in diesem Format, d.h.
07- 4-2009
oder eher
07-4-2009
oder
7-4-2009
oder doch
07-04-2009
Das genaue Format spielt eine wichtige Rolle, denn das Handbuch zeigt Dir, welche Formatspezifizierer Du nehmen musst.
Der erste Fall mit einem Leerzeichen wäre ganz schlimm. Dann müsstest Du noch Zwischenschritte vornehmen.
Baue Dir im ersten Schritt ein SELECT-Statement zusammen, dass Dir Deine Spalte mit str_to_date in ein Datum umwandelt, zum Beispiel im Fall von
07-04-2009
hätten wir:
Tage mit führender Null: %d
Bindestrich: -
Monate mit führender Null: %m
Bindestrich: -
Jahreszahl, vierstellig: %Y
somit kämen wir auf
SELECT
pf_datum1, -- das Originalformat
STR_TO_DATE(
pf_datum1, -- erster Parameter ist der Inhalt der Spalte im
-- Originalformat
'%d-%m-%Y' -- zweiter der Formatstring gemäß 07-04-2009
) umgewandelt -- mal wieder ein netter Spaltenname
-- ich verzichte auf AS, weil nicht jedes DBMS das
-- AS versteht
FROM -- aus der Tabelle, in
data -- der die Spalte mit dem Originalformat steht
-- ich weiß nicht, welche das ist
Wenn dies zufriedenstellende Ergebnisse liefert, so füge der Tabelle, die das Originalformat enthält, eine weitere Spalte vom Typ date hinzu und gib ihr einen vernünftigen Namen.
Anschließend fülle die neue Spalte mit einer UPDATE-Anweisung mit den umgewandelten Daten:
UPDATE
tabelle
SET
neue_datums_spalte = STR_TO_DATE(
pf_datum1,
'%d-%m-%Y'
)
Da Deine Anwendung vermutlich nur die Spalte im Originalformat füllt, wäre es angebracht, mittels Trigger dafür zu sorgen, dass bei jedem Neueintrag und jeder Änderung der Originalspalte die neue Datumsspalte gefüllt wird.
Alternativ kannst Du DATEDIFF auch mit
DATEDIFF(
CURDATE(),
STR_TO_DATE(pf_datum1, '%d-%m-%Y')
)
füttern.
Bitte denke daran, genau die Formatspezifizierer zu verwenden, die Du benötigst. Das können andere sein als ich hier beispielhaft aufgeführt habe.
Hast Du wirklich ein Leerzeichen drin, dann musst Du dieses zuerst eliminieren (mit geeigneten Stringfunktionen), damit Du STR_TO_DATE anwenden kannst.
Ich finde, das ist ein schönes Beispiel dafür, warum man beim Tabellendesign den am besten passenden Datentyp des DBMS verwenden sollte - und dass beliebte und verbreitete Software wie hier
Es ist eine Profilfeld in einem phpbb-Forum.
oft schludert nach dem Motto: "wird ja sonst nicht benötigt ...".
Freundliche Grüße
Vinzenz
Hallo Vinzenz,Tom und Ekki, also ich muss sagen, ihr seid einfach große klasse. Habe in den letzten Tagen durch euch wieder viel dazu gelernt und werde die neuen Tipps natürlich auch wieder ausprobieren und mich dann abschließend nochmals melden. Wollte mich nur schon mal bedanken für eure Hilfe und vor allem eure Geduld mit mir. Vg Ute
Hello,
Hallo Ekki, ich glaube, jetzt kommen wir der Sache näher. Also erstmal Entschuldigung wegen der "überlesenen" Frage. Es ist Mysql 5.0 und das Feld hat den Typ varchar, Größe 10. Es ist eine Profilfeld in einem phpbb-Forum. Ich hatte das auch als Datumsfeld im Forum (über den admin-Bereich im Forum) angelegt; in Mysql wird es aber als varchar angezeigt. Einfach ändern über den phpmyadmin geht nicht.
Füge eine neue Spalte mit dem Typ Date oder Datetime hinzu (je nachdem, was Du brauchst) und dann fülle diese Spalte anschließend mit Hilfe der Stringfunktionen. MySQL sollte bei passend angebotenem Format die Konvertierung in den Zielspaltentyp alleine schaffen.
Anschließend, wenn alles geklappt hat, kannst Du dann die kaputte Spalte löschen und die neue umbenennen.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Hello,
Das müsste ausgeschrieben 'as tage' heißen und ist der publizierte Name für die berechnete Spalte.
In deinem Resultset, dass Du von PHP aus erreichen kannst, steht also für die berechnete Spalte der Index ['tage'] im fetch_assoc()-Array.
Hallo Tom, ja das macht Sinn mit dem "as tage". Nur ich bekomme das nicht Feld nicht ausgelesen. Hier mal die Ausgabe:
$i =0;
while ($row = mysql_fetch_assoc($result))
{
$row = mysql_fetch_assoc($result);
print "{$row['name']} hat folgende Nummer: {$row['nummer'] und ist seit dem {$row['adat']}, das sind {$row['tage']} Tage, angemeldet<br>";
}
Sonst lass Dir doch einfach mal $row anzeigen:
$row = mysql_fetch_assoc($result);
echo "<pre>\r\n";
echo "htmlspecialchars(print_r($row,1));
echo "</pre>\r\n";
Ute
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Sonst lass Dir doch einfach mal $row anzeigen:
$row = mysql_fetch_assoc($result);
echo "<pre>\r\n";
echo htmlspecialchars(print_r($row,1));
echo "</pre>\r\n";
Hallo Tom, das habe ich getan. das Array zeigt alles richtig an, nur der Wert aus [tage] ist leer. Danke für eure Geduld und VG Ute
Hello,
Sonst lass Dir doch einfach mal $row anzeigen:
$row = mysql_fetch_assoc($result);
echo "<pre>\r\n";
echo htmlspecialchars(print_r($row,1));
echo "</pre>\r\n";Hallo Tom, das habe ich getan. das Array zeigt alles richtig an, nur der Wert aus [tage] ist leer. Danke für eure Geduld und VG Ute
Gerne geschehen.
Zeig doch nochmal das SQL-Statement, das Du nach Vinzenz' Vorschlag zusammengebaut hast. Da wird wohl der Fehler stecken.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg