3 Werte gleichzeitig abfragen, Statement optimieren

Tommy57

Erfahrenes Mitglied
Hallo,

ich bin recht frisch mit SQL und habe hier nen Statement geschrieben, wo ich euch einfach mal fragen wollte, ob man es so löst. Die Ergebnisse scheinen richtig zu sein.

Ich habe eine Tabelle "Aktienkurse", wo fast zu jedem Tag der jeweilige Tageswert drin steht, nun brauche ich den heutigen Stand, den vor 6 und den vor 12 Monaten von einem bestimmten Kurs. Hierbei ist die Performance sehr sehr wichtig, daher schreibe ich auch nicht 3 Statements, sondern nur 1.

Code:
SELECT day, value FROM aktienkurse WHERE id_kurs = $id AND day <= $vor12Monaten
UNION ALL 
    (SELECT day, value FROM aktienkurse WHERE id_kurs = $id AND day <= $vor6Monaten ORDER BY day DESC LIMIT 1)
UNION ALL
    (SELECT day, value FROM aktienkurse WHERE id_kurs = $id AND day <= $heute ORDER BY day DESC LIMIT 1)
ORDER BY day DESC LIMIT 3

Über Verbesserungsvorschläge würde ich mich sehr freuen.

Gruß, Tommy
 
Hmmm.... Soviel sortieren ist ungesund.
Ich würde mal eine Vergleichsmessung machen mit der GROUP BY Variante
SQL:
SELECT 
	MAX(day), 
	value 
FROM 
	aktienkurse 
WHERE 
	id_kurs = $id 
	AND day <= $vor12Monaten
GROUP BY id_kurs
UNION ....

Den letzten LIMIT kannst du vergessen. Ein UNION bei dem jeder SELECT höchstens ein Eintrag liefert, kann nicht mehr ausgeben.
 
Zuletzt bearbeitet von einem Moderator:
Super Idee, danke. nur hab ich da mal ne Frage.
Was wäre in den beiden Fällen, wenn der 6 Montae alte Wert identisch mit dem 12 Monate alten Wert wäre?
Und was wäre, wenn der letzte Preis, der mir vorliegen sollte, älter als 12 Monate ist, bei meiner Variante kriege ich da dann 3 Mal das selbe Ergebnis.

Ich teste es mal eben und sag, ob und wieviel schneller das Ganze ist.
Danke nochmal.


EDIT: Du hast ein Group By auf id_kurs, müsste der nicht auf Value(also dem Wert) stehen?
 
Zuletzt bearbeitet:
Also, ich habe das Statement mal getestet und es tut sich da so gut wie nix. Also es ist weder schneller noch langsamer. Hab ihn paar Hundert Durchläufe machen lassen und er braucht bei beiden Varianten in etwa gleich lang.

EDIT: Hab da jetzt einige Sachen ausprobiert und ich denke, so wie ich es habe, ist das okay. Danke auf jeden Fall für die Idee, nur bei deinem Statement kam ich um eine Sortierung nicht rum, da er mir sonst nicht die korrekten Werte geliefert hat, warum auch immer. Und mit der Sortierung komm ich auch da auf das selbe Ergebnis.

Danke nochmals
 
Zuletzt bearbeitet:
Das folgende könnte funktioniern und schneller sein, da nur 2 Zugriffe auf die aktienkurs-Tabelle durchgeführt werden ohne viele Sortierungen
SQL:
SELECT
	selectedDates.id_kurs,
	selectedDates.asOfDate,
	selectedDates.kursDate,
	kurs.value
FROM
	(
		SELECT ALL
			criteria.id_kurs,
			criteria.asOfDate,
			MAX(tab.day) AS kursDate
		FROM
			-- Die Kriterien abfüllen
			-- Die Dateums könnten auch in SQL berechnet werden
			(SELECT {$id} AS id_kurs, {$heute} AS asOfDate
			UNION ALL SELECT {$id}, {$vor6Monaten}
			UNION ALL SELECT {$id}, {vor12Monaten}
			) AS criteria
			-- Die Kursdatums zu den Kriterien aussuchen
			LEFT JOIN 
				aktienkurse AS tab
				ON criteria.id_kurs = tab.id_kurs 
				AND criteria.asOfDate >= tab.day
		GROUP BY
			criteria.id_kurs,
			criteria.asOfDate
	) AS selectedDates
	LEFT JOIN aktienkurse
		ON selectedDates.id_kurs = kurs.id_kurs
		AND selectedDates.kursDate = kurs.day;

Dier Criteria-Block könnte auch so umgesetzt werden, damit SQL die daten seleber berechnet
SQL:
SELECT @id_kurs := {$id} AS id_kurs, DATE(NOW()) AS asOfDate
UNION ALL SELECT @id_kurs, DATE_SUB(DATE(NOW()), INTERVAL 6 MONTH)
UNION ALL SELECT @id_kurs, DATE_SUB(DATE(NOW()), INTERVAL 12 MONTH)
 
Zuletzt bearbeitet von einem Moderator:
Oh das sieht cool aus.

Die Dateums könnten auch in SQL berechnet werden
Ich habe die in PHP schon vorberechnet und da ich dieses Statement mehrere Hundert mal starten muss, dachte ich, es spart Ressourcen, wenn ich es von PHP direkt eintragen lasse.


In Zeile 16 steht $vor6Monaten und in Zeile 17 ohne Dollar. Sind das Variablen und wo werden sie definiert? Kannst du mir das vllt kurz erklären, damit ich weiß, wie ich das schreiben muss. Immerhin sind es zwei Code-Blöcke.

Gruß



EDIT: OKAY, ich habe es hingekriegt^^.
Ich teste es gerade noch mal ein wenig...
 
Zuletzt bearbeitet:
So, ich habe das Statement jetzt getestet. Also mir gefällt das Statement um einiges besser, da ich immer drei Zeilen kriege und zusätzlich die drei Zeilen um eine Spalte ergänzen kann, wo ich den jeweiligen Key ablege (name = 'twelveMonthAgo', name = 'sixMonthAgo', name = 'today'), so muss ich auf der Seite von PHP keine blöden Abfragen machen, sondern kann den Wert gleich in den dazugehörigen Key speichern.

Schade an der Stelle ist nur, dass dein Statement rund 11-12% langsamer ist, als das, was ich vorher verwendet hatte. Ich werde zwar trotzdem deins verwenden, weil ich es sauberer finde, aber kann man da nicht noch was machen?

Gruß
 

Neue Beiträge

Zurück