# Letzten Eintrag eines Users anzeigen



## moondancer (27. Februar 2005)

Hallo, 

ich habe eine Tabelle mit der groben Struktur

Datum  |  User_ID  |  Daten..

Wobei Datum in der Form TT.MM.JJJJ vorliegt. Nun möchte ich den letzten Eintrag einer bestimmten User_ID anzeigen. Da das Datum nicht als Timestamp vorliegt kann ich schlecht mit "max" arbeiten. Gibt es trotzdem eine Möglichkeit dies in einer Abfrage zu bewerkstelligen? (DBS ist MySQL)

Viele Grüße
Christian


----------



## shutdown (28. Februar 2005)

Du musst dein Datumsfeld umstrukturieren (am besten per PHP-Skript)

Es muss so vorliegen: JJJJ-MM-TT

Dann können MySql-Funktionen damit arbeiten und ein max() müsste eigentlich auch funtkionieren

cu shutdown


----------



## Dennis Wronka (28. Februar 2005)

Wie waere es denn einfach anhand der Beitrags-ID zu bestimmen welcher der neueste ist?
So mach ich das auch, immerhin sollte die ID ja bei jedem neuen Eintrag um eins hochgezaehlt werden. Dementsprechend hat der neueste Eintrag die hoechste ID.


----------



## shutdown (28. Februar 2005)

> Wie waere es denn einfach anhand der Beitrags-ID zu bestimmen welcher der neueste ist?



Ist natürlich auch eine Lösung - wenn auch keine besonders schöne.

1) Eine Beitrags-ID ist im Grunde nur ein überflüssiges Feld, das normalerweise über (eh schon vorhandene Datums-Angaben und eine Count umgangen werden kann). Ich stimme zu, dass es vieles einfacher macht - und ich gebe zu, dass ich es mir auch oft so einfacher mache 

2) Wenn er sein Datumsfeld umstrukturiert, dann kann er später andere lustige Funktionen drauf los lassen, die für Auswertungen und ähnliches sehr interessant sein können.


----------



## moondancer (28. Februar 2005)

Hi,

eine ID ist leider nicht vorhanden.

@shutdown: 
Das wäre natürlich eine Lösung. Würdest Du das Format des Feldes dann auf "date" ändern? Hab mit dem Datentyp noch nicht gearbeitet...
Alternativ könnte ich ja auch gleich den timestamp speichern, oder hat das Nachteile?

Viele Grüße
Christian


----------



## Dennis Wronka (28. Februar 2005)

Aber ein ID-Feld hat man ja eigentlich eh immer in der Tabelle drin. Weiterhin ist das in der Regel auch der Primary Key und auch noch auto_increment, also quasi perfekt um die Reihenfolge festzustellen. Ich hab in meiner News-Tabelle auch das Datum mit drin, aber das nutz ich halt nur zur Anzeige, sortiert wird nach ID, natuerlich absteigend, sodass der neueste Eintrag oben steht..


----------



## shutdown (28. Februar 2005)

Du musst nicht unbedingt auf date ändern.

Ein varchar(10) funktioniert normalerweise auch.



> Aber ein ID-Feld hat man ja eigentlich eh immer in der Tabelle drin. Weiterhin ist das in der Regel auch der Primary Key und auch noch auto_increment, also quasi perfekt um die Reihenfolge festzustellen.



Wie gesagt - eine Möglichkeit, aber wirklich nicht die Beste.

Ein Primary Key auf eine (völlig von der effektiven Anwendung unabhängigen) Spalte verhindert z.B. nicht, dass du ein und den selben Eintrag zweimal schreiben kannst.


----------



## Dennis Wronka (28. Februar 2005)

Das ist richtig, ist ja auch nicht unbedingt immer erwuenscht das zu verhindern.
Wenn so ein ID-Feld da ist sollte das ja eindeutig sein.
Besonders wenn es um irgendwelche Beitraege handelt ist es durchaus sinnvoll, dass der Inhalt sich auch mal wiederholen kann.


----------



## shutdown (28. Februar 2005)

Es geht nicht darum, dass sich hin und wieder ein paar Zeilen wiederholen.

Aber der gesamte Eintrag wiederholt sich einfach nie  - sollte zumindest nicht


----------



## Dennis Wronka (28. Februar 2005)

Ist doch kein Problem, das ist bei meinen News auch durchaus moeglich, und ich finde das sinnvoll.
Wenn ich am 30.04.2005 schreiben will: "Heute Abend ist Mayday! Viel Spass!" und am 30.04.2006 das gleiche, dann funktioniert das wenigstens.

Da faellt mir ein, dieses Jahr ist Mayday leider ohne mich.


----------



## shutdown (28. Februar 2005)

den Primary Key auf Eintrag UND Datum und du kannst an jedem Tag des Jahres auf deine Mayday verweisen ;-)


----------



## Dennis Wronka (28. Februar 2005)

Einmal im Jahr reicht, ist ja nur am 30.04.
Aber nun zurueck zum Thema, sonst werden wir noch wegen offtopic verklagt.

Ich versteh ehrlich gesagt nicht, warum der Weg ueber die ID unsauber sein soll.
Der einfachste Weg ist halt die ID, da diese eindeutig ist. Wenn er zwei Eintraege am selben Tag schreibt und nur vom Datum ausgeht ist nicht ersichtlich welcher Eintrag der neueste ist.


----------



## shutdown (28. Februar 2005)

> Wenn er zwei Eintraege am selben Tag schreibt und nur vom Datum ausgeht ist nicht ersichtlich welcher Eintrag der neueste ist.



Punkt für dich 

Also moondancer - doch am besten den Timestamp verwenden (nimm am besten den von der PHP-Funktion time() - da bekommst du was du brauchst ;-) )


Die ID ist darum unsauber, weil man sie eigentlich nicht braucht und sie darum eine überflüssige Spalte darstellt.
In unserem Anwendungsbereich fällt das nicht zu sehr ins Gewicht, aber wenn's dann mal um größere Anwendungen (so ca. 20000 Einträge dürften da ausreichen) geht, da fallen dann überflüssige Spalten schon ins Gewicht


----------



## Dennis Wronka (28. Februar 2005)

shutdown hat gesagt.:
			
		

> Die ID ist darum unsauber, weil man sie eigentlich nicht braucht und sie darum eine überflüssige Spalte darstellt.
> In unserem Anwendungsbereich fällt das nicht zu sehr ins Gewicht, aber wenn's dann mal um größere Anwendungen (so ca. 20000 Einträge dürften da ausreichen) geht, da fallen dann überflüssige Spalten schon ins Gewicht



Na gut, das koennte sich dann vielleicht doch ein wenig auswirken.
Die Frage ist jetzt noch, kann er den Timestamp auch in ein vernuenftiges Datum/Zeit-Gebilde umwandeln um ihn gegebenenfalls mit auszugeben? Ansonsten waere das ja im Grunde genommen auch eine "ueberfluessige" Spalte, genau wie bei mir die ID.


----------



## shutdown (28. Februar 2005)

jep einen Timestamp kann man mit PHP sehr schön bearbeiten

http://www.php.net/date

Diese Funktion lässt eine Formatierte Datumsausgabe anhand des Timestamps zu.

Zum Beispiel:

date("d.m.Y", $timestamp) für z.B. 31.12.2004


----------



## Dennis Wronka (28. Februar 2005)

Okay, dann braucht er also nicht zusaetzlich ein Datumsfeld zur Ausgabe.
Die Uhrzeit ist im timestamp auch mit dabei, richtig?


----------



## shutdown (28. Februar 2005)

jep und noch viel mehr 

Schau dir einfach mal die Ausgabe-Möglichkeiten an: http://www.php.net/date


----------



## Dennis Wronka (28. Februar 2005)

Danke fuer die Info. Werd's mir mal anschauen.

Nachtrag:
So krieg ich uebrigens die Zeit (also Datum, Zeit Zeitzone) fuer meine News:
$newsdate=date("D d.m.Y, H:i:s T");


----------



## hpvw (28. Februar 2005)

Mach Dir doch eine Alias-Spalte mit STR_TO_DATE:

```
SELECT beitrag.USER_ID, STR_TO_DATE(beitrag.datum,'%d.%m.%Y') AS realDate WHERE User_ID = wenDuWillst ORDER BY realDate DESC LIMIT 0,1
```
Auf die Weise kannst Du Deine Tabelle auch in ein vernünftiges Format bringen.
1. Neue Spalte datum2 als DATETIME anlegen.
2. UPDATE beitrag SET datum2=STR_TO_DATE(datum,'%d.%m.%Y');
3. Alte Spalte datum löschen
4. Neue Spalte datum als DATETIME anlegen
5. UPDATE beitrag SET datum=datum2
6. Spalte datum 2 löschen.

Man kann soviel mehr machen, wenn man die Spalte als DATETIME definiert.

Die Uhrzeit, falls Du sie denn irgendwo speicherst, würde ich ins selbe Feld mit einbringen, daher DATETIME. Wenn Du keine Uhrzeit hast, kannst Du natürlich auch DATE nehmen.

Formatiert bekommst Du es auch:

```
SELECT User_ID, DATE_FORMAT(datum,'%d.%m.%Y') AS formattedDate FROM Beitrag
```

Weitere Infos, über Dinge, die mit DATETIME-Feldern anstellen kannst, findest Du in der Doku.

Und da hier Leute wieder mit dem UNIX-Timestamp anfangen: Hier die Diskussion dazu.

Nimm ein DATETIME-Feld und die MySQL-Funktion NOW() zum eintragen.

Gruß hpvw


----------



## shutdown (28. Februar 2005)

2 Dinge:

1) Die Diskussion kannst du ja wohl kaum als Argument für die Vorteile von Datetime verwenden - denn sie kam zu keinem Ergebnis!

2) Das Umformatieren wie du es beschriebe hast, is ja wohl ein wenig umständlich und in PHP wesentlich einfacher zu realisieren.

Aber da ich hier anscheinend immer wieder auf SQL-Puristen treffe, erwarte ich gar keine "freundliche" Antwort


----------



## hpvw (28. Februar 2005)

shutdown hat gesagt.:
			
		

> 1) Die Diskussion kannst du ja wohl kaum als Argument für die Vorteile von Datetime verwenden - denn sie kam zu keinem Ergebnis!


War auch nicht so gedacht. Aber man kann den Usern doch auch Lesestoff geben, um eine Entscheidung zu treffen.



			
				shutdown hat gesagt.:
			
		

> 2) Das Umformatieren wie du es beschriebe hast, is ja wohl ein wenig umständlich und in PHP wesentlich einfacher zu realisieren.


Da ich mir nicht sicher bin, welches umformatieren Du meinst, antworte ich mal zu allen drei Dingen, die ich geschrieben habe:

Mein erster Code dient dazu, bei der vorhandenen Datenstruktur im Query den entsprechenden Eintrag zu finden, den Moondancer haben will, da sehe ich keine (sinnvolle) Lösung mit PHP.

Der Weg, den ich zum Tabelle umstellen beschrieben habe, lässt sich im Prinzip auch verwenden, um das Feld in ein INT, welches einen Unix-Timestamp speichert, zu verwandeln. Es ist halt noch eine weitere (oder evtl. einfach eine andere) Funktion nötig. Wenn bereits Daten drin stehen, führt kein Weg, um so eine "Umformatierung" herum, wenn man die Tabelle in eine sinnvollere Struktur bringen will.

Ob man den dritten Code auf ein INT- oder auf ein DATETIME-Feld anwendet (bei INT natürlich in abgewandelter Form) oder die Formatierung  des INT anschließend in PHP macht, kann man selbst anhand der angeführten Diskussion entscheiden.



			
				shutdown hat gesagt.:
			
		

> Aber da ich hier anscheinend immer wieder auf SQL-Puristen ...


Ich nehme das mal als Kompliment  


			
				shutdown hat gesagt.:
			
		

> ... treffe, erwarte ich gar keine "freundliche" Antwort


Vielleicht keine freundliche und keine, die Dir zustimmt, aber ich hoffe doch, Du siehst meine Antwort wenigstens als sachlich an.

Gerade, wenn es ums Sortieren und "Filtern" geht, halte ich es für sinnvoll, dieses im SQL-Query und nicht in PHP zu machen. Dazu ist das Datum, wie es derzeit gespeichert ist, nur bedingt geeignet. Eine Umstellung auf einen (Unix-)Timestamp oder ein DATETIME-Feld (IMHO besser geeignet ) halte ich daher für sinnvoll.

Gruß hpvw


----------



## moondancer (28. Februar 2005)

wow, danke für die vielen Antworten. Also die Variante mit DATETIME kommt mir schon sehr entgegen. Denn ich möchte letztendlich die Kalenderwoche mit auslesen und das geht ja wohl bei DATETIME, wenn ich richtig verstanden hab. Somit spare ich mir die Implementierung in PHP - macht sich bei derzeit 15.000 Einträgen sicher bemerkbar. Ein ID-Feld gibt es übrigens wirklich nicht..

Vielleicht sollte ich mal  genauer spezifizieren, welche Operationen geplant sind - evtl. gibt es ja eine Lösung komplett in SQL...
Also die genaue Struktur der Tabelle sieht so aus:
Datum  |  Region_ID  |  User_ID  |  Preis1  |  Preis2  |  Preis3
Für jeden Tag und jede Region gibt es genau einen Eintrag. An Wochenenden keine Einträge.

Was ist geplant? Es soll für jede Kalenderwoche die Durchschnittspreise je Region ermittelt werden und in einer extra Tabelle abgelegt werden.
Es gibt ja die AVG-Funktion in SQL... Was meint Ihr, kann man das in einer SQL-Query unterbringen oder doch lieber PHP?

Viele Grüße
Christian


----------



## hpvw (28. Februar 2005)

Ich würde für Durchschnittspreise keine eigene Tabelle anlegen. Das entspräche einer redundanten Datenhaltung, welche in normalisierten Datenbanken nicht gewünscht ist.
Als Faustregel kann man sagen, dass Daten, die aus bestehenden Daten berechnet werden können nicht in der Datenbank gespeichert werden sollten.

Ich habe die Tabelle mal Preise genannt und angenommen, dass es eine Tabelle Region mit einem Attribut Name gibt. Datum müsste in diesem Fall vom Typ DATE oder DATETIME sein.

```
SELECT 
YEARWEEK(Preise.Datum,1) AS woche, 
Region.Name as Region, 
CONCAT(
  'Region ',
  Region.Name,
  ' (',
  Preise.Region_ID,
  ') in der Woche' ,
  YEARWEEK(Preise.Datum,1)
) as Gruppenbildung,
AVG(Preis1) as Durchschnittspreis1,
AVG(Preis2) as Durchschnittspreis2,
AVG(Preis3) as Durchschnittspreis3
FROM
Preise JOIN Region ON (Region.ID=Preise.Region_ID)
GROUP BY Gruppenbildung
ORDER BY Region, woche DESC
(Alternativ: ORDER BY woche DESC, Region)
```
Mit der User_ID weiss ich jetzt nicht viel anzufangen, aber ich denke, dass sie bei einer Durchschnittsbestimmung nicht relevant ist. Da ich mir gerade nicht sicher bin, ob man nach 2 Feldern gruppieren kann, habe ich das künstliche Feld Gruppenbildung eingeführt und es so formatiert, dass man es auch ausgeben könnte. Mit einem passenden Trennzeichen ließe sich das sicher performanter gestalten.
Außerdem soll das nur als Anregung dienen, da ich mir keine solche Datenbank aufsetze, um es zu testen. Es können also Fehler drin sein. Ggf. müsstest Du eine konkrete Fehlermeldung posten, damit ich mir das nochmal anschauen kann.

Gruß hpvw


----------



## shutdown (28. Februar 2005)

Das müsste grundsätzlich auch mit purem SQL möglich sein

Mit PHP ist es halt einfacher einen Workaround zu schreiben, wenn deine Befehle nicht so ganz tun was sie sollen ;-)

Die Kalenderwoche kannst du dir mit der date()-Funktion von PHP aus einem Timestamp problemlos erstellen lassen.


Was planst du denn überhaupt später mit den ermittelten Daten zu machen

Wenn du sie sowieso über ne Homepage ausgeben willst, dann würde ich empfehlen, gleich alles in PHP zu machen

Ich würde zum Beispiel in Abhängigkeit von der zu bearbeitenden Kalenderwoche (wird über das Skript festgelegt) ein Select erstellen (in PHP) und mit diesem die zugehörigen Daten ermitteln.

Die Durchschnittswerte kannst du entweder gleich in das SQL -Statement einbauen, oder du nutzt PHP (Werte durch mysql_affected_rows() sollte den Durchschnitt ergeben)

Was dann rauskommt kannst du dann gleich über ein Insert in deine Durchschnittstabelle schreiben.

cu shutdown


----------



## moondancer (1. März 2005)

vielen Dank das sieht sehr gut aus - werde es morgen mal testen und dann das Ergebnis posten.
Es ist so, dass die Preisdaten für die letzten 3 Tage in einer Tabelle auf der Homepage ausgegeben werden. Danach sind nur noch die Wochendurchschnitte relevant. Aus diesen sollen Diagramme erstellt werden. Die Tagespreise der Vergangenheit werden dann gelöscht - deshalb die zweite Tabelle...

Viele Grüße
Christian


----------

