Oder zerpflück mal das
SQL aus Antwort #3:
Zuerst
SQL-Code:
select -- uns interessieren nur die Daten zum EingabeDatum
FahrerNr,
VKBG
from Tagesumsatz
where Datum between :EingabeDatumVon and :EingabeDatumBis
Übergib zwei Parameter, denn mit Delphi kann man problemlos die Datumswerte für den zu verwendenden Zeitraum berechnen. Außerdem hat es den Charme, dass Du zu einem späteren Zeitpunkt, wenn sich z. B. die Anforderungen ändern, das
SQL für jeden beliebigen Zeitraum nutzen kannst. Damit kann man dann unverändert auch mal für 'ne Woche oder 'nen Monat oder auch nur 'ne Stunde, die Werte ermitteln (sofern im Datum auch der Zeitanteil enthalten ist).
Erst wenn dieses kurze
SQL Ergebnisse zu Deiner Zufriedenheit liefert, kümmerst Du dich bitte um den "Rest".
Der zweite Versuch geht dann mit:
SQL-Code:
select -- FahrerNr, Name und Umsatz nach Zahlart separieren
FahrerNr,
b.Name,
VKBG as Umsatz,
case when Zahlart = 1 then VKBG else 0 end as Bar,
case when Zahlart = 3 then VKBG else 0 end as Karte,
case when Zahlart = 2 then VKBG else 0 end as LS
from (
select -- uns interessieren nur die Daten zum EingabeDatum
FahrerNr,
VKBG
from Tagesumsatz
where where Datum between :EingabeDatumVon and :EingabeDatumBis
) TU
-- nur die Fahrerdaten zum EingabeDatum dazu holen,
-- anstatt zuerst alle Fahrerdaten zu beliebigem Datum zusammensuchen
-- und dann erst die zum EingabeDatum zu separieren.
left join Fahrer b on b.Nr = tu.FahrerNr
Erst wenn hier die Ergebnisse stimmen, wird die Summierung darum gebaut:
SQL-Code:
select -- Zuletzt die Summen je FahrerNr bilden
FahrerNr,
Name,
Sum(Umsatz) as Umsatz,
Sum(Bar) as Bar,
Sum(Karte) as Karte,
Sum(LS) as LS
from (
select -- FahrerNr, Name und Umsatz nach Zahlart separieren
FahrerNr,
b.Name,
VKBG as Umsatz,
case when Zahlart = 1 then VKBG else 0 end as Bar,
case when Zahlart = 3 then VKBG else 0 end as Karte,
case when Zahlart = 2 then VKBG else 0 end as LS
from (
select -- uns interessieren nur die Daten zum EingabeDatum
FahrerNr,
VKBG
from Tagesumsatz
where Datum between :EingabeDatumVon and :EingabeDatumBis
) TU
-- nur die Fahrerdaten zum EingabeDatum dazu holen,
-- anstatt zuerst alle Fahrerdaten zu beliebigem Datum zusammensuchen
-- und dann erst die zum EingabeDatum zu separieren.
left join Fahrer b on b.Nr = tu.FahrerNr
) a
Group by
FahrerNr,
Name;
Solltest Du bis hierher kommen und die Laufzeit immer noch nicht passen, dann kümmern wir uns auch noch um die Laufzeit. Dazu brauchen wir dann aber ein paar Infos mehr, z. B.: Datenmengen in den beiden Tabellen, wenn irgend möglich vollständige Tabellendefinitionen, Indexdefinitionen, ungefähre Infos zu den Mengenverhältnissen zwischen Fahrer und Tagesumsatz. Könntest Du uns ggfls. auch Testdaten zur Verfügung stellen ...?
PS.:
Meine SQLs sind oft von innen nach außen in diverse Unterabfragen aufgeteilt, weil meine Erfahrung zeigt, dass so die auftretenden Fehler oder Dateninkonsitenzen einfacher zu lokalisieren sind. Kurze SQLs, auf ein Minimum an Schreibarbeit reduziert, bedeuten nicht zwingend, dass dann auch die Laufzeit auf ein Minimum reduziert wird. Frei nach dem Motto: Möglichst früh die zu verarbeitende Datenmenge reduzieren, dann die benötigten Zusatzdaten aus anderen Tabellen dazuholen und auf der "Restmenge" dann die Rechenarbeit, wie Summierungen, Zählen, Gruppierungen und Sortierung durchführen (ungefähr so, als müsste ich mir die Infos aus einem Wust von Karteikarten in unterschiedlichen Karteikästen von Hand raussuchen. Wie komme ich da mit dem wenigsten Aufwand ans erwünschte Ergebnis? Verblüffenderweise klappt das bei der Nutzung von Datenbanken dann auch oft erstaunlich gut
.