jhe1960
Goto Top

MySQL Tabelle - Zeitangaben

Moinsen,
ich möchte Werte in eine MySQL Tabelle eingeben, die einer Zeitangabe entsprechen. Welchen Typ muss ich für diesen Wert eintragen?

So kommt der Wert aus einer Textdatei:

1:45.661

So soll er dann in der Tabelle stehen:

1:45.661

Die Tabelle sollte (u.a.) mit diesem Wert sortierbar sein.

z.B.

1:45.661
1:45.662
1:45.663
1:45.664
1:55.661

Wer kann mir da einen Tipp geben?

MfG
jhe

Content-ID: 193209

Url: https://administrator.de/forum/mysql-tabelle-zeitangaben-193209.html

Ausgedruckt am: 23.12.2024 um 04:12 Uhr

106949
106949 24.10.2012 um 10:21:57 Uhr
Goto Top
Hallo jhe,

einfach mal String (Text) nehmen, da es keinen Zahlentyp gibt, der den Doppelpunkt abbilden kann

LG
nxclass
nxclass 24.10.2012 aktualisiert um 11:53:19 Uhr
Goto Top
einfach mal String (Text) nehmen,
stimme zu - in VARCHAR() speichern - und ggf mit MICROSECOND() abfragen.

MySQL unterstützt keine Zeitangaben in Millisekunden. Ein Aufspalten des Zeitwertes um die Ergebnisse in 2 Spalten abzulegen (Sekunden, Millisekunden) bringt keine Vorteile.
jhe1960
jhe1960 24.10.2012 um 12:08:17 Uhr
Goto Top
Vielen Dank für die Info, ich probiere das dann mal so.
MfG
jhe
exchange
exchange 24.10.2012 um 20:45:15 Uhr
Goto Top
Hallo,
1. auf garkeinen Fall text nehmen
2. bitte nicht als varchar abspeichern

Wenn die Zahl hinter de Punkt Millisekunden sind, dann auch komplett als Millisekunden abspeichern. Ist doch bei einem select schnell sortiert und das DBMS hat am wenigstens arbeit.

Ansonsten ist diese Doku sinnvoll: http://dev.mysql.com/doc/refman/5.1/de/storage-requirements.html
Da kannst Du dann auch den passenden Zahlentyp auswählen.


Gruß
Heiko
nxclass
nxclass 25.10.2012 aktualisiert um 09:04:57 Uhr
Goto Top
, dann auch komplett als Millisekunden abspeichern
Wenn der TO vorhat mit den Daten zu rechnen, könnte man darüber nachdenken die Zeit als Zahl abzuspeichern und zwar in Millisekunden.
jhe1960
jhe1960 25.10.2012 um 10:15:58 Uhr
Goto Top
Moin,

es wird nicht gerechnet, es soll aber sortiert werden mit diesen Werten.

1:55.661 (Minuten:Sekunden.ZehntelHundertstelTausendstel). Wie müsste ich dass dann bewerkstelligen? Habt Nachsicht mit mir, älterer Herr mit wenig MySQL Kenntnissen face-smile

MfG
jhe
Biber
Biber 25.10.2012, aktualisiert am 24.02.2014 um 21:28:50 Uhr
Goto Top
Moin jhe1960,

in diesem Fall liegen die eher verhaltenen Antworten auf deine Frage auch daran, dass du dem (eigentlich recht brauchbaren) mySQL nun unbeabsichtigt etwas in den Schritt gefasst hast.

Die Krux ist

- du könntest diese Strings im Format "1:55.661" (Minuten:Sekunden.ZehntelHundertstelTausendstel)" zwar als Varchar() speichern inklusive der Doppelpunkte und dann zwar nicht damit rechnen, aber zumindest auf-/absteigend sortieren, wenn denn alle Datensätze nur einstellige Sekundenwerte haben. So etwas ist eine Rahmenbedingung, die in der Praxis niemand garantieren würde.

- immer "richtig" sortieren könntest du natürlich Time/Datetime-Werte. Leider leider leider kann mySQL zwar bei der Datums-/Zeitarithmetik mit Millisekunden rechnen, aber (nich' lachen jezz!) in MySQL werden Millisekunden bei Time/Timestamp-Datentypen nicht gespeichert.

- drittens könntest du die Werte als numerischen Wert speichern (z.B.als Integer), aber dann musst du es halt umrechnen. Im Beispiel "1:55.661" müsstest du also als Integer-Millisekundenwert errechnen und speichern "(1 Minute in Millisekunden) plus 55661 Millsekunden".

- Viertens könntest du auch die "1:55.661"etc-Werte in zwei Datenfeldern speichern, nämlich in einem Time/Timestampfeld (nur mit Sekundengenauigkeit) und den fractional-Anteil, die Millisekunden in einem Extra-Integer-Millisekundenfeld.

Ich würde vermutlich die vierte Variante wählen, auch wenn die noch nicht genannt wurde.

Im (für begrenzt optimistische Datenschaufler wie mich) absolut realitätsfernen Szenario "alle Zeitwerte haben IMMER dieselbe Textlänge == Länge("1:55:661")== 8 Zeichen und es wird NIE NIE NIE eine Ausnahme davon geben UND ich werde NIE NIE NIE mit den Zeiten rechnen wollen (z.B. Durchschnittswerte pro Gruppe)"
-> dann nimm Varchar und einen stumpfen Textvergleich für die Sortierung.

Grüße
Biber
jhe1960
jhe1960 25.10.2012, aktualisiert am 26.10.2012 um 10:55:19 Uhr
Goto Top
@ Biber:
Ojeh... face-wink

Erst mal vielen Dank, für deine ausführliche Antwort.

Grundsätzlich ist es so, dass es tatsächlich (fast) immer 8 Stellen sind. In ein paar sehr seltenen Ausnahmefällen, könnten die Minuten auch 2-stellig sein, langsamer Fahrer auf der Nordschleife....

Ich werde mal ein paar Varianten probieren.

Vielen Dank noch mal,
jhe

P.S.: ich kann auch deutlich besser kochen, als programmieren face-wink
jhe1960
jhe1960 28.11.2013, aktualisiert am 29.11.2013 um 10:23:08 Uhr
Goto Top
Moin liebes Adminstrator.de Forum. ich bin jetzt schon einen ganzen Schritt weiter, leider hakt es noch an einer Stelle...

Ich hänge bei der Abfrage. Es funktioniert, aber noch mit einem dummen Fehler. Das liegt sicher an meinen rudimentären MySQL Kenntnissen und dem Problem, dass einige Datensätze doppelt sind . Es soll jeweils (pro Fahrer) die schnellste Rundenzeit angezeigt werden. Wenn ich meine Abfrage ausführe, mit Limit 0,10, werden die Zeiten von nur 2 Fahrern angezeigt. Es sollte eigentlich von den Fahrern eine Top 10 Liste angezeigt werden. So ungefähr schaut es aus:

time  	        Fahrer 	    Minutes Seconds Milliseconds
108.5990 	Fahrer1 	1 	48 	599
108.5990 	Fahrer1 	1 	48 	599
108.5990 	Fahrer1 	1 	48 	599
108.5990 	Fahrer1 	1 	48 	599
108.5990 	Fahrer1 	1 	48 	599
108.5990 	Fahrer1 	1 	48 	599
108.5990 	Fahrer1 	1 	48 	599
108.6350 	Fahrer2 	1 	48 	635
108.6350 	Fahrer2 	1 	48 	635
108.6350 	Fahrer2 	1 	48 	635

Die Zeit 1:48.599 ist tatsächlich die schnellste Zeit von Fahrer1 und 1:48.635 ist die beste Zeit von Fahrer2.

Dargestellt sollen aber eigentlich die schnellste Zeit pro Fahrer, von 10 Fahrern.


Hier mal das "Machwerk":

 SELECT (
Minutes *60
) + ( Seconds ) + ( Milliseconds /1000 ) AS time, driver.Name AS Fahrer, tracking.Minutes AS Minutes, tracking.Seconds AS Seconds, tracking.Milliseconds AS Milliseconds
FROM trackerneu.tracks, trackerneu.driver, trackerneu.session, trackerneu.tracking, trackerneu.vehicle
WHERE tracking.TrackID =84
AND tracks.ID =84
AND tracking.DriverID = driver.ID
AND tracking.sessionID
IN ( 2, 3 )
AND tracking.vehicleID = vehicle.ID
ORDER BY time
LIMIT 0 , 10

Bitte nicht gleich erschlagen, ich habe mir das mühsam zusammengeschustert face-wink

Es geht also darum, was ich in meine Abfrage einfügen muss, damit nur die jeweils schnellste Zeit (kleinster Wert "time") pro Fahrer angezeigt wird? Also das rausfiltern der doppelten Einträge...

Weitere Infos gebe ich gerne, kann auch einen SQL-Dump zur Verfügung stellen, oder was immer auch gewünscht wird.

Gruß,
Juergen

//Edit:

Hier noch die Struktur der DB als PDF

1
Biber
Biber 01.12.2013 aktualisiert um 18:32:42 Uhr
Goto Top
Moin Jürgen,

versuch es so:
SELECT Top10Times.time
 , d.Name AS Fahrer
 , t.Minutes AS Minutes
 , t.Seconds AS Seconds
 , t.Milliseconds AS Milliseconds
FROM (select t.driverid
     , min ( ( t.Minutes *60) + ( t.Seconds ) + ( t.Milliseconds /1000 )) AS time
     , min(t.id) as id
      from trackerneu.tracking t
      Where t.TrackID =84
      and t.sessionId in (2, 3)
      group by driverId
      LIMIT 0 , 10     
 ) top10times
 -- trackerneu.tracks tx
    , trackerneu.tracking t
   , trackerneu.driver d 
   --, trackerneu.session s
    --, trackerneu.vehicle v
WHERE t.ID =Top10Times.Id
AND t.DriverID = d.ID

Mimik: ich hole mir (unter dem Aliasnamen "Top10Times") die 10 kleinsten Zeiten für die TrackId 84 und SessionId 1 oder 2 je Fahrer.
Und zusätzlich die ID dieses Datensatzes.

Über die Tracking.ID komme ich wieder an die Detaildaten Minutes, Seconds etc.

Die IMHO unnötigerweise verjointen Tabellen, aus denen kene Infos gebraucht werden, die habe ich auskommentiert.

Ungetestet.

Grüße
Biber
jhe1960
jhe1960 01.12.2013 aktualisiert um 19:18:16 Uhr
Goto Top
Hallo Biber,
vielen Dank für deine Antwort. Da ich MySQL nicht so beherrsche, was soll ich mit den einzelnen Buchstaben (Zeilenende) anfangen?
Liebe Grüße,
Jürgen

P.S.: kann es sein, dass da beim copy & paste etwas durcheinander gekommen ist?
Biber
Biber 01.12.2013 aktualisiert um 19:35:21 Uhr
Goto Top
Moin Jürgen,

die einzelnen Buchstaben hinter den Tabellennamen sind so genannte Aliasnamen,
Bedeutet, dass ich (s.o.) alle Felder der Tabelle trackerneu.tracking alias t ansprechen kann als t.id, t.minutes etc.

Hat 27 Vorteile.
Die 3 wichtigsten:

- Es macht das Statement lesbar und wartbar

- ich kann auch ohne Syntaxerror reservierte Worte als Feldnamen verwenden (minutes, seconds, user, alter)
und identische Spaltennamen in mehreren Tabellen ansprechen Denn ein t.id ist eindeutig ein Verweis auf EIN Feld in EINER Tabelle mit dem Alias t.

- Wenn sowohl die Tabellen einen Alias haben wie auch die Bedingungen im WHERE wie auch die Felder im SELECT-Teil, dann siehst du schnell, ob du alle Tabellen überhaupt benötigst (s.o). In deinem Select war z.B. die Tabelle Vehicle mit angegeben, aber weder mit einer anderen Tabelle verjoined noch wurde ein Feld von Vehicle angezeigt,

Grüße
Biber

Zu deinem P.S.
Ja, kann beim Copy&Paste immer sein.
Teste zuerst, ob hierbei etwas herauskommt:

Select * 
FROM (select t.driverid
     , min ( ( t.Minutes *60) + ( t.Seconds ) + ( t.Milliseconds /1000 )) AS time
     , min(t.id) as id
      from trackerneu.tracking t
      Where t.TrackID =84
      and t.sessionId in (2, 3)
      group by driverId
      LIMIT 0 , 10     
 ) top10times
B.
jhe1960
jhe1960 01.12.2013 aktualisiert um 23:07:29 Uhr
Goto Top
Hallo Biber,
vielen Dank. Ich habe mal getestet:

Select * 
FROM (select t.driverid,
      min( ( t.Minutes *60) + ( t.Seconds ) + ( t.Milliseconds /1000 )) AS time,
      min(t.id) as id
      from trackerneu.tracking t
      Where t.TrackID =84
      and t.sessionId in (2, 3)
      group by driverId
      LIMIT 0 , 10     
 ) top10times

Ergebnis:

driverid 	time 	id 	
51 	112.0140 	28883
53 	111.6640 	28920
54 	108.5990 	28862
57 	111.6300 	28843
68 	108.4440 	28836

Wobei es richtig ist, dass nur 5 Ergebnisse kommen, es gibt bei der Strecke erst 5 Fahrer in der DB.

Gruß,
Jürgen

Edit:

- Wenn sowohl die Tabellen einen Alias haben wie auch die Bedingungen im WHERE wie auch die Felder im SELECT-Teil, dann siehst du
schnell, ob du alle Tabellen überhaupt benötigst (s.o). In deinem Select war z.B. die Tabelle Vehicle mit angegeben,
aber weder mit einer anderen Tabelle verjoined noch wurde ein Feld von Vehicle angezeigt,


Vehicle war deshalb drin, falls ich das später brauche, wenn mehrere Events (mit unterschiedlichen Fahrzeugen) auf einer Strecke gefahren worden sind. Zur besseren Unterscheidung...
Biber
Biber 01.12.2013 um 22:46:10 Uhr
Goto Top
Moin Jürgen,

Und mit DESC ist die Reihenfolge schon mal richtig.
Hmm, hab ich's mit den Augen?

Mit "ORDER BY 2 Desc Limit whatever", also nach der zweiten Spalte (time) absteigend sortiert wäre die Sortierung in deinem Sinne.
So wie gepostet sortierst du nach der nichts aussagenden driverID.

Grüße
Biber
jhe1960
jhe1960 01.12.2013 um 23:07:04 Uhr
Goto Top
Hmmmm...ojeh...ich habs mit den Augen^^

vergiss einfach das nach dem Edit, ich lösch das raus. Machen wir da weiter, als ich deinen Schnippsel getestet habe face-smile

Gruß,
Jürgen
Biber
Biber 02.12.2013 um 08:10:07 Uhr
Goto Top
Moin Jürgen,

okay, machen wir mit dem Komplett-Statement weiter.
Denn etwas besser bekommen wir es noch hin.
SELECT Top10Times.time
 , d.Name AS Fahrer
 , t.Minutes AS Minutes
 , t.Seconds AS Seconds
 , t.Milliseconds AS Milliseconds
FROM (select t.driverid  -- gruppiert nach DriverId=Fahrer..
     , t.trackId -- ...und nach Rennstrecke
     , min ( ( t.Minutes *60) + ( t.Seconds ) + ( t.Milliseconds /1000 )) AS time
     , min(t.id) as id
      from trackerneu.tracking t
      Where t.sessionId in (2, 3) -- das gilt für alle Rennstrecken (?)
      group by t.driverId, t.TrackID
   
 ) top10times
   -- trackerneu.tracks tx
  , trackerneu.tracking t
   , trackerneu.driver d 
   --, trackerneu.session s
    --, trackerneu.vehicle v
WHERE t.ID =Top10Times.Id
AND t.TrackID =84 
-- auf eine Rennstrecke filtern erst hier in der WHERE-Clause,
-- wo es auch jeder sucht und erwartet
AND t.DriverID = d.ID
ORDER BY 1 DESC
LIMIT 0 , 10     

Grüße
Biber
jhe1960
jhe1960 02.12.2013 aktualisiert um 16:32:13 Uhr
Goto Top
Guten morgen,
vielen Dank, ich habe getestet:

SELECT Top10Times.time,
d.Name AS Fahrer,
t.Minutes AS Minutes,
t.Seconds AS Seconds,
t.Milliseconds AS Milliseconds
FROM (select t.driverid,
      t.trackId,
      min((t.Minutes *60) + (t.Seconds) + (t.Milliseconds /1000)) AS time,
      min(t.id) as id
      from trackerneu.tracking t
      Where t.sessionId in (2, 3)
      group by t.driverId,
      t.TrackID   
 ) top10times,
trackerneu.tracking t,
trackerneu.driver d   
WHERE t.ID =Top10Times.Id
AND t.TrackID =84 
AND t.DriverID = d.ID
ORDER BY 1 DESC
LIMIT 0 , 10

Ergebnis:

time 	Fahrer 	Minutes 	Seconds 	Milliseconds 	
112.0140 	Fahrer1	1 	53 	375
111.6640 	Fahrer2 	2 	2 	565
111.6300 	Fahrer3 	1 	52 	299
108.5990 	Fahrer4 	        1      	55 	720
108.0210 	Fahrer5    1       52 	946

Es stimmen leider weder die Zeiten (sind nicht die Bestzeiten der jeweiligen Fahrer), noch die Reihenfolge...

Habe ich irgendwas falsch übernommen?

Zu deiner Frage
-- das gilt für alle Rennstrecken (?)

Jupp, eventuell ersetze ich das noch mit einem include, ebenso die TrackID.

Gruß,
Jürgen
Biber
Biber 02.12.2013 aktualisiert um 11:41:57 Uhr
Goto Top
Moin Jürgen,

ja nee...is' klar..
a) weil ich blöd bin
b) und weil heute Montach ist..


STREICHE: group by t.driverId, t.TrackID --> damit bekommen wir die jeweils 10 schnellsten Fahrten jedes Fahrers über alle Strecken
SETZE: : group by t.TrackID, t.driverID --> damit bekommen wir die jeweils 10 schnellsten Fahrer je Strecke, und die wollen wir


Sorry, eigentlich fasse ich montachmorgens auch nichts mit mehr als drei Zeilen an...

Grüße
Biber
jhe1960
jhe1960 02.12.2013 aktualisiert um 16:33:04 Uhr
Goto Top
Jo, die Montage... face-wink

Getestet:

SELECT Top10Times.time,
d.Name AS Fahrer,
t.Minutes AS Minutes,
t.Seconds AS Seconds,
t.Milliseconds AS Milliseconds
FROM (select t.driverid,
      t.trackId,
      min((t.Minutes*60) + (t.Seconds) + (t.Milliseconds/1000)) AS time,
      min(t.id) as id
      from trackerneu.tracking t
      Where t.sessionId in (2,3)
      group by t.TrackID, t.driverID
 ) top10times,
trackerneu.tracking t,
trackerneu.driver d   
WHERE t.ID =Top10Times.Id
AND t.TrackID =84 
AND t.DriverID = d.ID
ORDER BY 1 ASC
LIMIT 0 , 10

Ergebnis:

time 	Fahrer 	Minutes 	Seconds 	Milliseconds 	
108.0210 	Fahrer1 	1 	52 	946
108.5990 	Fahrer2 	1 	55 	720
111.6300 	Fahrer3 	1 	52 	299
111.6640 	Fahrer4 	2 	2 	565
112.0140 	Fahrer5 	1 	53 	375

Das stimmt leider auch nicht face-sad

Ich habe mal nachgerecnet:

1:52.946 = 112.946 Millisekunden

In der Tabelle steht aber bei 1:52.946 = 108.0210

Die korrekte Zeit wäre bei Fahrer 1 = 1:48.021

1:48.021 = 108.0210

Also wird "time" korrekt ausgelesen und bezogen auf "time" stimmt dann auch die Sortierung. Irgendwas geht dann aber bei der Umrechnung in die Zeit (Minuten, Sekunden, Millisekunden) schief, oder?

Gruß,
Jürgen
Biber
Biber 02.12.2013 um 15:17:10 Uhr
Goto Top
Moin Jürgen,

na okay, den anderen Denkfehler schiebe ich mal nicht auf den Montag - die Verknüpfung über Min(id) = t.id klappt so nicht.

Also dann ein paar Zeichen länger:

SELECT Top10Times.time,
d.Name AS Fahrer,
t.Minutes AS Minutes,
t.Seconds AS Seconds,
t.Milliseconds AS Milliseconds
FROM (select t.driverid,
      t.trackId,
      min((t.Minutes*60) + (t.Seconds) + (t.Milliseconds/1000)) AS time
      from trackerneu.tracking t
      Where t.sessionId in (2,3)
      group by t.TrackID, t.driverID
 ) top10times,
trackerneu.tracking t,
trackerneu.driver d   
WHERE t.trackID=Top10Times.TrackId
AND ((t.Minutes*60) + (t.Seconds) + (t.Milliseconds/1000)) =Top10Times.time
AND t.TrackID =84 
AND t.DriverID = d.ID
ORDER BY 1 ASC
LIMIT 0 , 10

Grüße
Biber
jhe1960
jhe1960 02.12.2013 um 16:03:59 Uhr
Goto Top
Yippie Yah Yei... face-wink

Es funktioniert. Vielen Dank für die Arbeit, die du dir gemacht hast und für deine Geduld!

Gruß,
Jürgen & die Fahrer von project-race.de
jhe1960
jhe1960 09.12.2013 aktualisiert um 11:50:37 Uhr
Goto Top
Hallöle, da bin ich wieder...

anscheinend werden die doppelten doch nicht richtig rausgefiltert:

SELECT Top10Times.time,
	d.Name AS Fahrer,
	t.Minutes AS Minutes,
	t.Seconds AS Seconds,
	t.Milliseconds AS Milliseconds
		FROM (select t.driverid,
		t.trackId,
		min((t.Minutes*60) + (t.Seconds) + (t.Milliseconds/1000)) AS time
		from trackerneu.tracking t
		Where t.sessionId in (2,3)
		group by t.TrackID, t.driverID
		) top10times,
		trackerneu.tracking t,
		trackerneu.driver d   
	WHERE t.trackID=Top10Times.TrackId
	AND ((t.Minutes*60) + (t.Seconds) + (t.Milliseconds/1000)) =Top10Times.time
	AND t.TrackID = 88 
	AND t.DriverID = d.ID
	ORDER BY 1 ASC
	LIMIT 0 , 10

Ergebnis:

time 	Fahrer 	Minutes 	Seconds 	Milliseconds 	
89.7410 	Fahrer 1 	1 	29 	741
89.8200 	Fahrer 2 	1 	29 	820
90.1320 	Fahrer 3 	1 	30 	132
90.1320 	Fahrer 3 	1 	30 	132

Woran könnte das noch liegen?
Biber
Lösung Biber 09.12.2013, aktualisiert am 22.02.2014 um 12:21:20 Uhr
Goto Top
Moin jhe1960,

eigentlich kann es nur daran liegen, dass in der unteren WHERE-Clause noch ein
AND t.sessionId in (2,3)

fehlt.

Oder aber:
Es sei denn, der Wolfgang.hat tatsächlich zwei Bestrunden mit exakt derselben Zeit hingelegt.

Wenn es das ist: Ergänze oben direkt nach dem Wort SELECT noch das Wort DISTINCT.

Grüße
Biber
jhe1960
jhe1960 09.12.2013 um 11:48:16 Uhr
Goto Top
Moin Biber,
mit AND t.sessionId in (2,3) gab es keine Änderung, aber mit DISTINCT klappt es nun.
Vielen Dank für dein Hilfe, obwohl mal wieder Montag ist face-smile
Gruß,
Jürgen

P.S.: der Teufel ist ein Eichhörnchen.. face-wink
jhe1960
jhe1960 22.02.2014 aktualisiert um 12:38:40 Uhr
Goto Top
Moin,
ich hänge da noch an einer Kleinigkeit, zumindest wahrscheinlich für euch eine Kleinigkeit...

Ich möchte Daten ab einem bestimmten Datum auslesen. In phpMyAdmin funktioniert das auch:


SELECT driver.Name AS Fahrer, COUNT( tracking.Lap ) AS lAps
FROM tracking, driver
WHERE tracking.TrackID =82
AND tracking.DriverID = driver.ID
AND tracking.VehicleID =124
AND CreatedAt < '2014-02-02 00:00:00'
GROUP BY Fahrer
ORDER BY lAps DESC
LIMIT 0 , 5

Ich würde gerne den Bereich von CreatedAt als include einfügen, nur leider geht das nicht. Es kommen dann immer Fehlermeldungen bei der Ausgabe, wenn ich das wie folgt mache:

include('tracknum.php');

$sql = "SELECT driver.Name AS Fahrer, COUNT(tracking.Lap) AS lAps FROM tracking, driver where tracking.TrackID = 82 AND tracking.DriverID = driver.ID AND tracking.VehicleID = 124 AND CreatedAt in ($createdat) GROUP BY Fahrer ORDER BY lAps DESC LIMIT 0,5";

Zeile in der include Datei:

$createdat > '2012-02-02 00:00:00';

Fehlermeldung:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') GROUP BY Fahrer ORDER BY lAps DESC LIMIT 0,5' at line 1

Wenn ich andere Daten, wie z.B. die TrackID per include verwende, funktioniert es einwandfrei.

Wahrscheinlich ist es wirklich nur eine Kleinigkeit, aber ich komme nicht drauf...Hilfe face-wink
Gruß,
Jürgen
Biber
Biber 24.02.2014 aktualisiert um 00:16:13 Uhr
Goto Top
Moin jhe1960,

wenn in der tracknum.php stehen würde
$createdat = '2012-02-02 00:00:00';
...dann müsste dein Statement in dieser Form klappen
...
$sql = "SELECT driver.Name AS Fahrer, COUNT(tracking.Lap) AS lAps FROM tracking, driver where tracking.TrackID = 82 AND tracking.DriverID = driver.ID AND tracking.VehicleID = 124 AND CreatedAt < $createdat GROUP BY Fahrer ORDER BY lAps DESC LIMIT 0,5";  

Oder eventuell sicherheitshalber gecastet mit
...and CreatedAt < cast($createdat as DateTime)...

Grüße
Biber
jhe1960
jhe1960 24.02.2014 um 08:14:07 Uhr
Goto Top
Moin Biber,
vielen Dank, ich habe es getestet. Was soll ich sagen...es geht leider nicht. Es kommt wieder die Fehlermeldung:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '00:00:00 GROUP BY Fahrer ORDER BY lAps DESC LIMIT 0,5' at line 7  

Aber halt...es ist ja Montag face-wink

Grüße,
Jürgen
Biber
Biber 24.02.2014, aktualisiert am 25.02.2014 um 22:36:38 Uhr
Goto Top
Moin jhe1060,

ich mag Montage ja auch...
versuche es mal so:

$sql = "SELECT driver.Name AS Fahrer, COUNT(tracking.Lap) AS lAps FROM tracking, driver where tracking.TrackID = 82 AND tracking.DriverID = driver.ID AND tracking.VehicleID = 124 AND CreatedAt < '".$createdat."' GROUP BY Fahrer ORDER BY lAps DESC LIMIT 0,5";  

Wenn das nicht hilft, dann müssen wir auf eine/n mySQL-Kundige/n warten... oder auf einen Dienstag... face-wink

[Edit] Etwas lesbarer wäre es so:
$sql  = "SELECT driver.Name AS Fahrer, COUNT(tracking.Lap) AS lAps";  
$sql .= " FROM tracking, driver";  
$sql .= " WHERE tracking.TrackID = 82";  
$sql .= " AND tracking.DriverID = driver.ID";  
$sql .= " AND tracking.VehicleID = 124";  
$sql .= " AND CreatedAt < '".$createdat."' ";  
$sql .= " GROUP BY Fahrer ORDER BY lAps DESC LIMIT 0,5";  
[/Edit]

Grüße
Biber
jhe1960
jhe1960 24.02.2014 aktualisiert um 09:41:37 Uhr
Goto Top
Moin Biber,
juhu, es funktioniert. Hast du eventuell noch eine Idee, wie ich es hinbekommen könnte, das "<" bzw. ">" in der include Datei zu verwenden?

Im Moment schaut es ja so aus:

$createdat = '2013-02-02 00:00:00';   

Also z.B. :

SELECT driver.Name AS Fahrer, COUNT( tracking.Lap ) AS lAps
FROM tracking, driver
WHERE tracking.TrackID in ($track)
AND tracking.DriverID = driver.ID
AND tracking.VehicleID in ($car)
AND CreatedAt = ('".$createdat."')  
GROUP BY Fahrer
ORDER BY lAps DESC
LIMIT 0 , 5

und dafür dann in der include:

$createdat > '2013-02-02 00:00:00';   

Leider funktioniert das so nicht...

Gruß,
Jürgen
Biber
Biber 24.02.2014 aktualisiert um 21:31:01 Uhr
Goto Top
Moin jhe1960,

das Hinterlegen eines "<" oder ">"-Zeichens in einer Variablen/in einer include-Datei würde ich nicht als Option wählen, selbst wenn es rein handwerklich ginge. Das mindert die Lesbarkeit des Statements und - viel wichtiger- nimmt dem Optimizer jegliche Möglichkeit, irgendwelche Zugriffspfade zu bestimmen.

Wenn du denn flexiblen Zugriff auf "Datum Kleiner als"/"Datum größer als"/"Datum gleich" über diese Include-Datei brauchst, dann definiere dort zwei Variablen:

$mincreatedat = '2013-02-02 00:00:00';  
$maxcreatedat = '2013-03-31 00:00:00';  

und ändere dein $sql in
SELECT driver.Name AS Fahrer, COUNT( tracking.Lap ) AS lAps
FROM tracking, driver
WHERE tracking.TrackID in ($track)
AND tracking.DriverID = driver.ID
AND tracking.VehicleID in ($car)
AND CreatedAt >= ('".$mincreatedat."')  
AND CreatedAt <= ('".$maxcreatedat."')  
GROUP BY Fahrer
ORDER BY lAps DESC
LIMIT 0 , 5 

So kannst du alle Fälle abbilden.
Ich habe hier bewusst die zwei Bedingungen "<=" und ">=" genommen statt
.."AND CreatedAt BETWEEN ('".$mincreatedat."') and ('".$maxcreatedat."')
, da mySQL meiner Erinnerung nach den Max-Wert/die Obergrenze ausschliesst.

Du würdest also, wenn mincreatedat und maxcreatedat gleich sind, oder allgemein wenn Obergrenze und Untergrenze gleich sind, mit BETWEEN niemals ein Ergebnis erhalten.

Grüße
Biber
jhe1960
jhe1960 24.02.2014 aktualisiert um 10:48:24 Uhr
Goto Top
Sehr cool, es funktioniert einwandfrei. Vielen Dank!
Gruß,
Jürgen

SELECT driver.Name AS Fahrer, COUNT( tracking.Lap ) AS lAps
FROM tracking, driver
WHERE tracking.TrackID in ($track)
AND tracking.DriverID = driver.ID
AND tracking.VehicleID in ($car)
AND CreatedAt >= ('".$mincreatedat."')  
AND CreatedAt <= ('".$maxcreatedat."')  
GROUP BY Fahrer
ORDER BY lAps DESC
LIMIT 0 , 5

<?php
/* StreckenID*/
$track = 82;
/* Streckenname*/
$stname = 'Zhuhai';  
/* Trainings SessionID*/
$session = '2';  
/* Quali SessionID*/
$qsession = '3';  
/* Fahrzeug ID */
$car = '124';  
/* Datum */
$mincreatedat = '2014-02-20 00:00:00';  
$maxcreatedat = '2014-12-31 00:00:00';  
/* SessionID : 1 = Training 1, 2 = Training 2, 3 = Qualifikation, 4 = WarmUp, 5 = Race 1, 6 = Race 2*/
?>
jhe1960
jhe1960 17.05.2014 aktualisiert um 00:59:57 Uhr
Goto Top
Moinsen,
ich bin jetzt auf ein kleines Problem gestossen...

Wenn ich nur 1 Fahrzeug auswerte, funktioniert alles, wie es soll. Es wird pro Fahrer die schnellste Rundenzeit ausgegeben.

Wenn ich jedoch mehrere Fahrzeuge (gemischtes Fahrzeugfeld) habe, bekomme ich bei jedem Fahrer die schnellste Zeit von jedem Fahrzeug ausgegeben.

$sql = "SELECT DISTINCT Top10Times.time,  
	d.Name AS Fahrer,
	t.Minutes AS Minutes,
	t.Seconds AS Seconds,
	t.Milliseconds AS Milliseconds
		FROM (select t.driverid,
		t.trackId, t.VehicleID,
		min((t.Minutes*60) + (t.Seconds) + (t.Milliseconds/1000)) AS time
		from trackerneu.tracking t
		Where t.sessionId in ($session)
		group by t.TrackID, t.driverID, t.VehicleID
		) top10times,
		trackerneu.tracking t,
		trackerneu.driver d   
	WHERE t.trackID=Top10Times.TrackId
	AND ((t.Minutes*60) + (t.Seconds) + (t.Milliseconds/1000)) =Top10Times.time
	AND t.TrackID = $track 
	AND t.DriverID = d.ID
	AND t.sessionId in ($session)
	AND t.VehicleID in ($car)
	AND CreatedAt >= ('".$mincreatedat."')   
	AND CreatedAt <= ('".$maxcreatedat."')   
	ORDER BY 1 ASC
	LIMIT 0 , 5";  

Include:

$car = '54,123,125,126,127';  

5 verschieden Fahrzeuge werden gefahren.

Ausgabe IST:

1	Fahrer 1	00:54.415
2	Fahrer 1	00:54.714
3	Fahrer 2	00:54.734

Die erste Zeit in diesem Beispiel, stammt von dem Fahrzeug mit der t.VehicelID 54 und die 2. Zeit stammt von dem Fahrzeug mit der t.VehicelID 123. Beide Zeiten wurden von Fahrer 1 gefahren.

Ausgegeben werden soll aber pro Strecke nur die schnellste Zeit pro Fahrer. In diesem Fall wäre das also die von der t.VehicelID 54.

Ausgabe SOLL:

1	Fahrer 1	00:54.415
2	Fahrer 2	00:54.734

Ich habe jetzt schon stundenlang rumgefummelt, komme aber auf keinen "grünen Zweig"...

Über Hilfe würde ich mich sehr freuen.

Gruß,
Jürgen
Biber
Lösung Biber 17.05.2014 aktualisiert um 17:40:15 Uhr
Goto Top
Moin jhe1960,

naja, verwunderlich ist aber das ausgegebene Ergebnis nicht wirklich,

In der "group by"-Clause des "Top10Times"-Subselect steht schwarz auf weiss (oder zumindest dunkel auf hellem Grund)
... group by t.TrackID, t.driverID, t.VehicleID ..
... also gruppieren/ermittle die Bestzeiten je Kombination Track/Fahrer/Fahrzeug.
und das macht die Query - - works as designed.

Für die jetzt gewünschte Abfrage musst du das letzte Gruppierfeld "t.VehicleID" aus der Group-By-Klausel entfernen und die t.VehicleID auch aus der Feldliste der "Top10Times" rausnehmen.

So in etwa sollte es werden:
$sql = "SELECT DISTINCT Top10Times.time,  
	d.Name AS Fahrer,
	t.Minutes AS Minutes,
	t.Seconds AS Seconds,
	t.Milliseconds AS Milliseconds
		FROM (select t.driverid,
		t.trackId, -- raus: t.VehicleID,
		min((t.Minutes*60) + (t.Seconds) + (t.Milliseconds/1000)) AS time
		from trackerneu.tracking t
		Where t.sessionId in ($session)
	AND t.VehicleID in ($car) -- diese Bedingung nach oben
		 group by t.TrackID, t.driverID -- Raus: , t.VehicleID
		) top10times,
		trackerneu.tracking t,
		trackerneu.driver d   
	WHERE t.trackID=Top10Times.TrackId
	AND ((t.Minutes*60) + (t.Seconds) + (t.Milliseconds/1000)) =Top10Times.time
	AND t.TrackID = $track 
	AND t.DriverID = d.ID
	AND t.sessionId in ($session)
-- Bedingung ging nach oben..
	AND CreatedAt >= ('".$mincreatedat."')   
	AND CreatedAt <= ('".$maxcreatedat."')   
	ORDER BY 1 ASC
	LIMIT 0 , 5";  

Grüße
Biber
.
jhe1960
jhe1960 17.05.2014 aktualisiert um 17:41:17 Uhr
Goto Top
Moinsen Biber,
mal wieder, mein Retter in der Not!

Vielen Dank & ein schönes Wochenende!

P.S.: diesmal habe ich es vor Montag geschafft face-smile
jhe1960
jhe1960 17.05.2014 aktualisiert um 19:09:16 Uhr
Goto Top
Hm...

hast du das so gemeint:

$sql = "SELECT DISTINCT Top10Times.time,  
	d.Name AS Fahrer,
	t.Minutes AS Minutes,
	t.Seconds AS Seconds,
	t.Milliseconds AS Milliseconds
		FROM (select t.driverid,
		t.trackId,
		min((t.Minutes*60) + (t.Seconds) + (t.Milliseconds/1000)) AS time
		from trackerneu.tracking t
		Where t.sessionId in ($session)
		AND t.VehicleID in ($car)
		group by t.TrackID, t.driverID
		) top10times,
		trackerneu.tracking t,
		trackerneu.driver d   
	WHERE t.trackID=Top10Times.TrackId
	AND ((t.Minutes*60) + (t.Seconds) + (t.Milliseconds/1000)) =Top10Times.time
	AND t.TrackID = $track 
	AND t.DriverID = d.ID
	AND t.sessionId in ($session)
	AND CreatedAt >= ('".$mincreatedat."')   
	AND CreatedAt <= ('".$maxcreatedat."')   
	ORDER BY 1 ASC
	LIMIT 0 , 5";  

Weil...irgendwie passt das noch nicht:

1	Fahrer 1	00:54.118
2	Fahrer 1	00:54.998
3	Fahrer 2	00:54.998

Gruß,
Jürgen
Biber
Biber 18.05.2014 aktualisiert um 12:26:12 Uhr
Goto Top
Moin Jürgen,

uups, da fehlt wohl noch ein Feld in dem Join zwischen Top10Times und tracking.
Bitte ergänze nach Zeile 16 noch ein
AND Top10Times.driverID = t.DriverID

Und (was jetzt nichts mit diesem Problem zu tun hat) nimm auch die gestern "nach oben verschobene Bedingung"
AND t.VehicleID in ($car)
noch mal redundant wieder mit rein eine Zeile tiefer.
Denn auch da könnte es zu falschen Verjoinungen kommen bei konstruierbaren Datenkonstellationen.

Grüße
Biber.
jhe1960
jhe1960 18.05.2014 um 13:12:41 Uhr
Goto Top
Zitat von @Biber:

Moin Jürgen,

uups, da fehlt wohl noch ein Feld in dem Join zwischen Top10Times und tracking.
Bitte ergänze nach Zeile 16 noch ein
AND Top10Times.driverID = t.DriverID

Und (was jetzt nichts mit diesem Problem zu tun hat) nimm auch die gestern "nach oben verschobene Bedingung"
AND t.VehicleID in ($car)
noch mal redundant wieder mit rein eine Zeile tiefer.
Denn auch da könnte es zu falschen Verjoinungen kommen bei konstruierbaren Datenkonstellationen.

Grüße
Biber.

Moinsen Biber,

ich habe das so ergänzt, wie ich es verstanden habe...passt das so?

$sql = "SELECT DISTINCT Top10Times.time,  
	d.Name AS Fahrer,
	t.Minutes AS Minutes,
	t.Seconds AS Seconds,
	t.Milliseconds AS Milliseconds
		FROM (select t.driverid,
		t.trackId,
		min((t.Minutes*60) + (t.Seconds) + (t.Milliseconds/1000)) AS time
		from trackerneu.tracking t
		Where t.sessionId in ($session)
		AND t.VehicleID in ($car)
		group by t.TrackID, t.DriverID
		) top10times,
		trackerneu.tracking t,
		trackerneu.driver d   
	WHERE t.trackID=Top10Times.TrackId AND Top10Times.driverID = t.DriverID
	AND t.VehicleID in ($car) 
	AND ((t.Minutes*60) + (t.Seconds) + (t.Milliseconds/1000)) =Top10Times.time
	AND t.TrackID = $track 
	AND t.DriverID = d.ID
	AND t.sessionId in ($session)
	AND CreatedAt >= ('".$mincreatedat."')   
	AND CreatedAt <= ('".$maxcreatedat."')   
	ORDER BY 1 ASC
	LIMIT 0 , 5";  

Es scheint zu funktionieren. Vielen Dank für Deine Hilfe.

Noch einen schönen Sonntag!
Jürgen
jhe1960
jhe1960 10.06.2014 um 18:32:19 Uhr
Goto Top
Moinsen,
wir haben jetzt auf rFactor2 umgestellt und ich habe leider feststellen müssen, dass die Logfiles fehlerbehaftet sind. Die Milliseconds werden 3- und 4-stellig in die Datenbank geschrieben. Kann ich das irgendwie im Query abfangen, dass bei Milliseconds nur die ersten 3 Stellen angezeigt werden?

SELECT DISTINCT Top10Times.time,
	d.Name AS Fahrer,
	t.Minutes AS Minutes,
	t.Seconds AS Seconds,
	t.Milliseconds AS Milliseconds
		FROM (select t.driverid,
		t.trackId,
		min((t.Minutes*60) + (t.Seconds) + (t.Milliseconds/1000)) AS time
		from trackerrf2.tracking t
		Where t.sessionId in ($session)
		AND t.VehicleID in ($car)
		group by t.TrackID, t.DriverID
		) top10times,
		trackerrf2.tracking t,
		trackerrf2.driver d   
	WHERE t.trackID=Top10Times.TrackId AND Top10Times.driverID = t.DriverID
	AND t.VehicleID in ($car) 
	AND ((t.Minutes*60) + (t.Seconds) + (t.Milliseconds/1000)) =Top10Times.time
	AND t.TrackID = $track 
	AND t.DriverID = d.ID
	AND t.sessionId in ($session)
	AND CreatedAt >= ('".$mincreatedat."')   
	AND CreatedAt <= ('".$maxcreatedat."')   
	ORDER BY 1 ASC
	LIMIT 0,5

Mit verschwitzten Grüßen,
Jürgen
Biber
Biber 10.06.2014 aktualisiert um 19:57:02 Uhr
Goto Top
Moin Jürgen,

da hast du dir aber ein schön entspannendes Hobby zugelegt... sicherlich das Richtige zum Abchillen bei dieser Hitze.

Also: natürlich als erster Tipp: gewöhn dem "der-in-die-Datentabelle-schreibt"-Prozess das ab, je nach Laune oder Wochentag mal drei, mal vier Ziffern in die Tabelle zu schreiben.

Wenn wir es aber momentan als gegeben/nicht abstellbar hinnehmen müssen, dann müssen wir wohl (oder übel) eine Fallunterscheidung machen. Auf SQL heisst dat dann SELECT CASE WHEN expr THEN bla ELSE blubb END.

Wenn ich das Problem richtig verstanden habe, dann stehen im Feld "milliseconds" zB die Werte
11 --> der Wert meint 11 Millisekunden == 0,011 sec
365 --> der Wert meint 365 Millisekunden == 0,365 sec
2345 --> dieser Wert meint 234,5 Millisekunden == 0,2345 sec.

Mit meinen geringen Mathekenntnissen bzw Erinnerungsbruchstücken aus der Schulzeit würden mir zwei Stategien einfallen, um jeweils auf ein "genormtes" Ergebnis zu kommen:
a) Wenn Input-Wert < 1000 dann dividiere durch 1000 andernfalls dividiere durch 10000
b) [mit brutaler impliziter Typkonvertierung.] Dividiere Inputwert durch 10 hoch Maximum(Länge(Inputwert), 3)

die zweite Variante ist eher was für EXCELaner.
Wenn du da in einer Tabelle in Zellen A1/A2/A3 die Werte 11/365/2345 stehen hättest, dann wäre die Formel in Zelle B1 ungefähr
=A1/10^MAX(LÄNGE(A1);3)
Würde funktionieren - aber brutalstmögliche implizite Typkonvertierung lassen wir mal für Excel-Anwendungen und somit in SQL-Statements draussen.


Variante a) würde also bedeuten, wir interpretieren die t.milliseconds unterschiedlich, je nachdem ob dort ein Wert < 1000 oder >= 1000 abgelegt ist.

Nur als proof-of-concept:

SELECT t.Milliseconds AS originalMilliseconds 
             , CASE when  t.milliseconds < 1000 then t.milliseconds else t.milliseconds/10 end as Normmsec
             , CASE when  t.milliseconds < 1000 then t.milliseconds/1000 else t.milliseconds/10000 end as NKsec
FROM trackerrf2.tracking t
LIMIT 0,50

Wenn mit dieser (ungetesteten) Probe-Abfrage brauchbare Werte für die beiden errechneten Felder "Normmsec" (soll sinngemäß Norm-Millisekunden bedeuten) und NKmsec (lies: Nachkomma-Sekunden) angezeigt werden, dann können wir überall dort, wo jetzt ein "t.milliseconds" in der Abfrage steht, eine der CASE-Varianten einbauen.

Aber prüfe bitte erst, ob ich das Problem richtig verstanden habe und was so eine TestAbfrage liefert.

Grüße
Biber
jhe1960
jhe1960 10.06.2014 aktualisiert um 20:41:31 Uhr
Goto Top
Hallo Biber,

jo, entspannt ist was anderes...

Das hat phpMyAdmin ausgespuckt:

 originalMilliseconds 	Normmsec 	NKsec 	
42 	42 	0.0420
7693 	769.3000 	0.7693
2853 	285.3000 	0.2853
5217 	521.7000 	0.5217
6438 	643.8000 	0.6438
4879 	487.9000 	0.4879
7266 	726.6000 	0.7266
2379 	237.9000 	0.2379
5989 	598.9000 	0.5989
1782 	178.2000 	0.1782
9905 	990.5000 	0.9905
6051 	605.1000 	0.6051
6823 	682.3000 	0.6823
4292 	429.2000 	0.4292
2925 	292.5000 	0.2925
537 	537 	0.5370
9198 	919.8000 	0.9198
2811 	281.1000 	0.2811
3389 	338.9000 	0.3389
3577 	357.7000 	0.3577
2161 	216.1000 	0.2161
7026 	702.6000 	0.7026
293 	293 	0.2930
2107 	210.7000 	0.2107
7657 	765.7000 	0.7657
4324 	432.4000 	0.4324
549 	549 	0.5490
5452 	545.2000 	0.5452
2143 	214.3000 	0.2143
5583 	558.3000 	0.5583
5874 	587.4000 	0.5874
947 	947 	0.9470
4440 	444.0000 	0.4440
9443 	944.3000 	0.9443
8536 	853.6000 	0.8536
9565 	956.5000 	0.9565
1246 	124.6000 	0.1246
3765 	376.5000 	0.3765
8270 	827.0000 	0.8270
7665 	766.5000 	0.7665
2562 	256.2000 	0.2562
625 	625 	0.6250
347 	347 	0.3470
4631 	463.1000 	0.4631
6643 	664.3000 	0.6643
6097 	609.7000 	0.6097
4147 	414.7000 	0.4147
6602 	660.2000 	0.6602
4820 	482.0000 	0.4820
3517 	351.7000 	0.3517

Ich hoffe, es ist brauchbar...

Mir würden halt 3 Stellen bei Milliseconds reichen. (3517 351.7000 0.3517 = 0.351)

Grüße,
Jürgen

P.S.: es hat unglaubliche 30° in der Bude...
Biber
Biber 10.06.2014 aktualisiert um 22:32:07 Uhr
Goto Top
Moin Jürgen,

na ja, der Rest ist eigentlich nur noch das Ersetzen der t.Milliseconds-Werte durch die Fallunterunterscheidung.

Um die Millisekunden einheitlich auf 3 Stellen zu trimmen, gäbe es die Funktionen FLOOR() bzw ROUND().

Sprich: wenn der Originalwert die Zahl 3517 wäre, was dann 351,7 msec wären, dann würde FLOOR(3157/10) es "abschneiden" auf die Ganzzahl 351.
Die Funktion ROUND() dagegen würde es in diesem Fall aufrunden als ROUND(3517/10) auf die Ganzzahl 352.

Ich würde ja eher "runden" statt die letzte Stelle abzuschneiden, aber das kannst du machen wiedewutt.

Dein Statement sähe (ungefähr) so aus nach dem Ersetzen von t.milliseconds durch CASE WHEN..END
SELECT DISTINCT Top10Times.time,
	d.Name AS Fahrer,
	t.Minutes AS Minutes,
	t.Seconds AS Seconds,
	case when t.Milliseconds < 1000 then t.Milliseconds
             else Round(t.Milliseconds/10) end    AS Milliseconds
		FROM (select t.driverid,
		t.trackId,
		min((t.Minutes*60) + (t.Seconds) + (
                case when t.Milliseconds<1000 then t.milliseconds/1000
                     else Round(t.milliseconds/10000) end  )) AS time
		from trackerrf2.tracking t
		Where t.sessionId in ($session)
		AND t.VehicleID in ($car)
		group by t.TrackID, t.DriverID
		) top10times,
		trackerrf2.tracking t,
		trackerrf2.driver d   
	WHERE t.trackID=Top10Times.TrackId AND Top10Times.driverID = t.DriverID
	AND t.VehicleID in ($car) 
	AND ((t.Minutes*60) + (t.Seconds) + (
            case when t.Milliseconds<1000 then t.milliseconds/1000
            else Round(t.milliseconds/10000) end)) =Top10Times.time
	AND t.TrackID = $track 
	AND t.DriverID = d.ID
	AND t.sessionId in ($session)
	AND CreatedAt >= ('".$mincreatedat."')   
	AND CreatedAt <= ('".$maxcreatedat."')   
	ORDER BY 1 ASC
	LIMIT 0,5


Kann sein, dass ich jetzt eine Klammer-Auf zuviel oder eine Klammer-Zu zuwenig habe - ich habe es eben nur im Editor versucht.

Das Prinzip sollte aber erkennbar sein.
Und: ja - das Statement ist dadurch um 20% länger geworden.
Aber: nein - die Laufzeit geht nicht im selben Verhältnis nach oben.

Grüße
Biber
jhe1960
jhe1960 11.06.2014 aktualisiert um 00:34:40 Uhr
Goto Top
Hallo Biber,
erst mal vielen Dank, dass Du Dir die Zeit nimmst, mir bei diesem blöden Problem zu helfen.

Die Milliseconds schauen schon mal sehr gut aus, ich folge Deiner Argumentation und finde Round auch besser face-wink

Nur irgendwie stimmt die Reihenfolge noch nicht:

1	Fahrer 1	02:01.127
2	Fahrer 1	02:00.561
3	Fahrer 2	02:01.187
4	Fahrer 1	02:01.137
5	Fahrer 3 	02:01.298
6	Fahrer 3 	02:00.958
7	Fahrer 3 	02:01.488
8	Fahrer 4	02:04.397
9	Fahrer 4	02:04.302
10	Fahrer 4	02:03.540

Im Moment sieht es so aus, als würden von jedem Fahrer die Bestzeiten von allen Fahrzeugen angezeigt. Es soll aber nur die absolute Bestzeit, egal mit welchem der 6 Fahrzeuge ($car), angezeigt werden.

Ratlose Grüße,
Jürgen

//Edit:

Ich habe das jetzt mal nur mit 1 Fahrzeug ausgeführt und es wird auch nicht richtig sortiert und time schaut auch seltsam aus:

SELECT DISTINCT Top10Times.time,
	d.Name AS Fahrer,
	t.Minutes AS Minutes,
	t.Seconds AS Seconds,
	case when t.Milliseconds < 1000 then t.Milliseconds
             else Round(t.Milliseconds/10) end AS Milliseconds
		FROM (select t.driverid,
		t.trackId,
		min((t.Minutes*60) + (t.Seconds) + (
                case when t.Milliseconds<1000 then t.milliseconds/1000
                     else Round(t.milliseconds/10000) end  )) AS time
		from trackerrf2.tracking t
		Where t.sessionId = 2
		AND t.VehicleID = 139
		group by t.TrackID, t.DriverID
		) top10times,
		trackerrf2.tracking t,
		trackerrf2.driver d   
	WHERE t.trackID=Top10Times.TrackId AND Top10Times.driverID = t.DriverID
	AND t.VehicleID = 139
	AND ((t.Minutes*60) + (t.Seconds) + (
            case when t.Milliseconds<1000 then t.milliseconds/1000
            else Round(t.milliseconds/10000) end)) =Top10Times.time
	AND t.TrackID = 120
	AND t.DriverID = d.ID
	AND t.sessionId = 2

	ORDER BY 1 ASC
	LIMIT 0,3

time 	Fahrer 	Minutes 	Seconds 	Milliseconds 	
121.0000 	Fahrer 1 	2 	1 	187
121.0000 	Fahrer 2 	2 	1 	137
121.0000 	Fahrer 3 	2 	1 	298
Biber
Biber 11.06.2014 aktualisiert um 15:17:44 Uhr
Goto Top
Moin Jürgen,

sorry, heute schiebe ich es mal auf die sommerliche Hitze....("Montag" fällt ja leider als Ausrede aus).

Ich habe gestern zuviel gecopy&pasted, denn die ROUND()-Funktion ist nur nötig bei der "Berechnung" des Feldes "Milliseconds" im Resultset,

In den Berechungen der Zeit ist ein Runden der Nachkommastellen auf den nächstliegenden Integerwert ... ääähm... nicht zielführend.
Siehst du ja in deinem unteren 3-Zeilen-Resultset.
Bei allen drei Fahrern werden aus 2 min+1 sec -> 121sec (ok) und aus den zur Ganzzahl geROUNDeten 0,187sec (und den folgenden Werten) logischerweise glatte 0sec.
Daher kommen die auch bei einem "ORDER BY 1 ASC", also nach der ersten Spalte sortiert in irgendeiner zufälligen Reihenfolge - die sind ja "gleichwertig"

Also - ich will nicht nochmal das Statement komplett zitieren - nimm in der Zeile 11 und 23 des Statements die Funktion ROUND() bitte raus, also in diesen Zeilen vom "else" bis zum "end" nur noch else t.milliseconds/10000 end stehen lassen.

Grüße
Biber
jhe1960
jhe1960 11.06.2014 um 14:23:56 Uhr
Goto Top
Juhu...wieder ein Sieg!

Vielen Dank, Biber, sehr nett von Dir.

Gruß,
Jürgen
jhe1960
jhe1960 19.10.2014 aktualisiert um 19:58:37 Uhr
Goto Top
Moinsen,
ich muss diesen Fred noch mal aus der Versenkung holen...

Wir sind mit unserer Datenbank umgezogen und ich bekomme jetzt mit obiger Abfrage eine Fehlermeldung:

Unknown column 'Top10Times.time' in 'field list'  

Das aktuelle Script:

$sql = "SELECT DISTINCT Top10Times.time,  
	d.Name AS Fahrer,
	t.Minutes AS Minutes,
	t.Seconds AS Seconds,
	Round (t.Milliseconds/10) AS Milliseconds
		FROM (select t.driverid,
		t.trackId,
		min((t.Minutes*60) + (t.Seconds) + (t.Milliseconds/10000)) AS time
		from db548229178.tracking t
		Where t.sessionId in ($allsession)
		AND t.VehicleID in ($car)
		group by t.TrackID, t.DriverID
		) top10times,
		db548229178.tracking t,
		db548229178.driver d   
	WHERE t.trackID=Top10Times.TrackId AND Top10Times.driverID = t.DriverID
	AND t.VehicleID in ($car) 
	AND ((t.Minutes*60) + (t.Seconds) + (t.Milliseconds/10000)) =Top10Times.time
	AND t.TrackID = $track 
	AND t.DriverID = d.ID
	AND t.sessionId in ($allsession)
	AND CreatedAt >= ('".$mincreatedat."')   
	AND CreatedAt <= ('".$maxcreatedat."')   
	ORDER BY 1 ASC
	LIMIT 0,5";  

Der alte Datenbankname war trackerrf2, der neue ist db548229178.

Hier auch noch ein Link zur php-Info: http://www.project-race.de/Phpinfo.php

Kann mir bitte jemand auf die Sprünge helfen?

Schönen Sonntag,
Jürgen

//Edit: ich möchte noch erwähnen, dass andere Scripte, die ebenfalls auf diese DB zugreifen, einwandfrei funktionieren...ich bin echt ratlos
Biber
Biber 19.10.2014 aktualisiert um 20:04:42 Uhr
Goto Top
Moin Jürgen,

ich hätte nur zwei Erklärungen für dieses Migrationsproblem.
a) entweder ist eine der Parametervariablen (noch) nicht richtig gesetzt worden nach der Umstellung
b) bei der "neuen" DB-Instanz macht der leichtsinnigerweise gewählte Feldname "time" Probleme, weil das ein reserviertes Wort in SQL ist.

Bitte prüfen, ob die Abfrage mit dem Feldnamen "zeit" statt "time" läuft und ob alle Parameter richtig sind.

Grüße
Biber
jhe1960
jhe1960 19.10.2014 um 22:01:47 Uhr
Goto Top
Hallo Biber,
vielen Dank, dass Du Dir die Zeit nimmst...

Wenn ich die Variablen durch feste Werte ersetze und das in phpMyAdmin ausführe, kommt dieselbe Fehlermeldung. Ich prüfe deinen Lösungsansatz und werde berichten.
Gruß,
Jürgen
jhe1960
jhe1960 19.10.2014 um 22:04:36 Uhr
Goto Top
Leider nur eine Änderung der Fehlermeldung...

Unknown column 'Top10Times.zeit' in 'field list'  
jhe1960
jhe1960 19.10.2014 um 22:13:30 Uhr
Goto Top
Ich bin gerade durch einen Zufall auf den Fehler gestossen...

In Zeile 16: top10times

habe ich in Top10Times geändert. Jetzt geht es wieder. Mit dem selben Script, ohne die Änderung, funktioniert es auf dem alten Server...

Verstehen muss ich das nicht, oder?

Gute Nacht & schönen Wochenstart face-wink

Jürgen
exchange
exchange 19.10.2014 um 22:16:06 Uhr
Goto Top
Hi,
schau Dir mal den Wert lower_case_table_names auf beiden Servern an.

Gruß
jhe1960
jhe1960 19.10.2014 aktualisiert um 23:28:41 Uhr
Goto Top
Danke für den Tipp face-wink das erklärt das Problem.
Gruß,
Jürgen