kleinerChemiker
Here to stay
|
in einer tabelle sind u.a. folgende felder: serial, name, account, zeit
dabei handelt es sich um die daten von charakteren eines rollenspiels. jeder char hat eine unique serial. auf einem account können mehrere char's liegen. jeden tag kommt für jeden char ein neuer eintrag hinzu.
nun suche ich alle chars, bei gegebenen account. allerdings will ich pro char nur eine zeile und zwar die, wo zeit am höchsten (->aktuellsten) ist. mit folgendem query bekomme ich fast das, was ich will. problem ist nur, daß es mir immer die zeile ausspuckt, wo die zeit am niedrigsten (also am ältesten) ist. folglich könnte ich 'zeit DESC' im ORDER BY weglassen, da es nichts bringt.
SELECT serial, name, account, zeit FROM chars WHERE account LIKE '$account' GROUP BY serial ORDER BY zeit DESC , account, name
wie bekomme ich immer den aktuellsten eintrag? der aktuellste eintrag eines chars muß nicht zwangsläufig die zeit der letzten eintragung haben. denn wenn der char gelöscht wird, werden keine weiteren eintragungen mehr vorgenommen.
tia
MIK
|
watchout
Legendundead
|
Welche mysql-version?
|
kleinerChemiker
Here to stay
|
4.1.10-nt, also subqueries möglich. hab mir bezüglich eh schon gedanken gemacht, nur hab ich noch nie mit subqueries gearbeitet bzw. auch keine ahnung davon.
SELECT serial AS s, name, account, zeit FROM chars WHERE account LIKE '$account' AND zeit=(SELECT max(zeit) FROM chars WHERE serial=s GROUP BY serial) GROUP BY serial ORDER BY account, name
wobei die fett geschriebene 's' die gerade aktuelle serial der jeweiligen zeile ist.
tia
MIK
|
pong
Addicted
|
SELECT serial, name, account, zeit FROM chars WHERE account LIKE '$account' GROUP BY serial HAVING MAX(zeit) ORDER BY zeit DESC , account, name pong
|
kleinerChemiker
Here to stay
|
ist zwar gültig, liefert aber ein leeres ergebnis. wobei having lt. doku nicht optimiert wird.
|
Ringding
Pilot
|
Das von pong schaut recht unsinnig aus, das von kleinerChemiker besser. Nur das group by im inneren select erscheint mir recht sinnfrei. Aber Achtung: es gibt dann immer große Augen, wenn es zwei Charaktere mit der gleichen Zeit gibt, dann kommen nämlich plötzlich mehrere Zeilen raus und nicht nur eine, wie man es erwarten könnte.
|
kleinerChemiker
Here to stay
|
zu einem zeitpunkt gibt es keine chars mit identen serials. also zu jedem zeitpunkt ist die serial unique. allerdings kommen die serials öfters vor, da sie bei jedem zeitpunkt einmal vorkommen können.
das group by im inneren ist, weil ich ja max() nur bei nem group by verwenden kann und auch nur 1 ergebnis haben darf. das problem bei dem von mir ist (m.e.) daß ich mich nicht auf die serial im äußeren beziehen kann. denn jede serial kann einen anderen letzten eintragszeitpunkt haben.
|
watchout
Legendundead
|
ist zwar gültig, liefert aber ein leeres ergebnis. wobei having lt. doku nicht optimiert wird. naja, "HAVING MAX(zeit)" is irgendwie kompletter Fehlschuss  SELECT * FROM chars
INNER JOIN (
SELECT MAX(zeit) as maxzeit FROM chars
GROUP BY serial) AS fake
ON(chars.zeit=fake.maxzeit)
WHERE account LIKE '$account'
GROUP BY serial
ORDER BY zeit DESC , account, name
Das is jetzt aber nur ein Schuss ins Blaue, weil ich weder testdaten noch ein MySQL 4.1.x hab  Aber ich denke so sollts gehn... *schluck*
|
kleinerChemiker
Here to stay
|
ich bin begeistert  es scheint genau das auszuspucken, was ich möchte. ich würd auch gerne so gut ins balue schießen können  wobei ich eigentlich nicht verstehe, wie das eigentlich funzt, aber hauptsache es funzt *g* edit: ha, jetzt hab ichs doch verstanden. aber soo hätt ich wohl nie gedacht.
|
watchout
Legendundead
|
|
kleinerChemiker
Here to stay
|
ja, es geht wirklich. einziger nachteil, der mir in kurzen tests auffiel: es schient ziemlich performance hungrig zu sein. was vielleicht aber auch daran liegt, daß der table knapp 50mb groß ist. oder hab ich index schlecht gewehlt? hab nen primary key über serial&zeit und einen index auf account.
|
watchout
Legendundead
|
hmm... Ein zusätzlicher Index auf "zeit", sowie "serial" (einzeln) sollte was bringen. (Aus sicht des einen Queries hier könntest du den Primary Key müllen, aber ich weiss ja nicht was du sonst damit machst) Aber ja, der Query is performancelastig weil er wahrscheinlich einen Temptable intern macht. Irgendwo in der Doku steht das, dass er einen macht wenn er Subselects oder auch Joins auf die gleiche Table macht. (is irgendwie Nachvollziehbar) Zusätzlich beschleunigen kannst es sicher wennst ne zusätzliche Table machst in dem du pro Char immer nur einen Entry mit <serial,zeit> hast. Das is jedoch reine Geschwindigkeits-Optimierung. Sollte man anfangs mal ausser acht lassen. PS: gewehlt
|
kleinerChemiker
Here to stay
|
jo, weiß eh wie man wählen schreibt  aber beim schnellen tippen sind die finger manchmal schneller als das hirn. ich hab dann noch queries, in der art: SELECT * FROM chars WHERE serial=xxx AND (zeit=aaa OR zeit=bbb ....) ich sollte mir mal wirklich ein buch durchlesen, damit ich weiß wann ich welche indexe (oder sind das indizes?) verwende.
|
watchout
Legendundead
|
SELECT * FROM chars WHERE serial=xxx AND (zeit=aaa OR zeit=bbb ....) statt (x=a or x=b or x=c or...) verwende in mysql besser x IN(a,b,c,...) Das kann mysql besser optimieren - zahlt sich bereits bei EINEM or aus  ja und dafür sollt der primary sinnvoll sein imo - also ist berechtigt wie ich dachte
|