AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi SQl Abfrage sehr langsam
Thema durchsuchen
Ansicht
Themen-Optionen

SQl Abfrage sehr langsam

Ein Thema von tkhandel · begonnen am 21. Jun 2024 · letzter Beitrag vom 27. Jun 2024
Antwort Antwort
Seite 2 von 4     12 34      
Delphi.Narium

Registriert seit: 27. Nov 2017
2.458 Beiträge
 
Delphi 7 Professional
 
#11

AW: SQl Abfrage sehr langsam

  Alt 25. Jun 2024, 10:03
Wenn DateTime, aber (beide Seiten) ohne Zeitanteil, kann man sich Cast as Date sparen.

Wenn mit Zeitanteil und :EingabeDatum ohne Zeitanteil dann eher sowas: where Datum between :von and :bis
:von wird im Programm mit sowas wie Trunc(Now) und :bis mit Trunc(Now + 1) - 1 / 86400000 (= eine Millisekunde) gefüllt, das ergibt dann sinngemäß sowas wie where Datum between 25.06.2024 00:00:00.000 and 25.06.2024 23:59:59.999
Dann dürfte der Index auch genutzt werden können.

Geht es nur um das Datum ohne Zeitanteil sollte where datum >= Cast(:Eingabedatum as Date) and datum < Cast(:Eingabedatum + 1 as Date) funktionieren. Wenn :Eingabedatum ohne Zeitanteil geliefert wird, verkürzt sich das dann auf where datum >= :Eingabedatum and datum < :Eingabedatum + 1

Der Flaschenhals im Ausgangs-SQL dürfte aber die spaltenweisen Summierungen per Sub-Select sein. Hier muss die Datenbank eine sehr große Menge von Abfragen starten, je Ergebniszeile vier Stück und die jeweils ohne 'nen Index verwenden zu können.
  Mit Zitat antworten Zitat
tkhandel

Registriert seit: 2. Jan 2022
Ort: Arnsberg im Sauerland
84 Beiträge
 
Delphi 10.4 Sydney
 
#12

AW: SQl Abfrage sehr langsam

  Alt 25. Jun 2024, 17:27
Ich habe mal alles probiert aber es kommt immer der gleiche Fehler
den ich nicht lokalisieren kann

select
FahrerNr,
b.Name,
Sum(VKBG) as Umsatz,
Sum(case when Zahlart = 1 then VKBG else 0 end) as Bar,
Sum(case when Zahlart = 3 then VKBG else 0 end) as Karte,
Sum(case when Zahlart = 2 then VKBG else 0 end) as LS
From Tagesumsatz t Left join Fahrer b on b.Nr = t.FahrerNr
where datum >= :Eingabedatum and datum < :Eingabedatum + 1
Group by FahrerNr, Name;


Unsuccessful execution caused by a system error that precludes
successful execution of subsequent statements.
Dynamic SQL Error.
expression evaluation not supported.
--------------------------------------------------------------
SQLCODE: -902
GDSCODE: 335544569
Jürgen
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.852 Beiträge
 
Delphi 11 Alexandria
 
#13

AW: SQl Abfrage sehr langsam

  Alt 25. Jun 2024, 17:35
Ich vermute mal der Error kommt vom Versuch den Parameter zu inkrementieren:

where datum >= :Eingabedatum and datum < :Eingabedatum + 1 Versuch mal
where datum >= :Eingabedatum and datum < DateAdd( day, 1, :Eingabedatum) Btw. Ich würde die (Tabellen-)Aliase konsequent verwenden.
Markus Kinzler
  Mit Zitat antworten Zitat
tkhandel

Registriert seit: 2. Jan 2022
Ort: Arnsberg im Sauerland
84 Beiträge
 
Delphi 10.4 Sydney
 
#14

AW: SQl Abfrage sehr langsam

  Alt 25. Jun 2024, 22:43
Hallo, ich glaube ehr es liegt irgendwie an

Sum(case when Zahlart = 1 then VKBG else 0 end) as Bar

auch kennt er dateadd nicht das scheint ja eine udf zu sein die ich nicht habe.
kann es sein das es bei der IBToGo bzw. IBLite Einschränkungen im Fuktionsumfang gibt?
Jürgen
  Mit Zitat antworten Zitat
Benutzerbild von IBExpert
IBExpert

Registriert seit: 15. Mär 2005
655 Beiträge
 
FreePascal / Lazarus
 
#15

AW: SQl Abfrage sehr langsam

  Alt 26. Jun 2024, 05:29
mach das mal mit 2 parametern statt mit einem und den dann mit +1 zu verändern.
das scheint interbase nicht brauchbar umzusetzen.

außerdem sollte eigentlich auch interbase between können

where datum between :Eingabedatum_von and :Eingabedatum_bis


Ich habe mal alles probiert aber es kommt immer der gleiche Fehler
den ich nicht lokalisieren kann

select
FahrerNr,
b.Name,
Sum(VKBG) as Umsatz,
Sum(case when Zahlart = 1 then VKBG else 0 end) as Bar,
Sum(case when Zahlart = 3 then VKBG else 0 end) as Karte,
Sum(case when Zahlart = 2 then VKBG else 0 end) as LS
From Tagesumsatz t Left join Fahrer b on b.Nr = t.FahrerNr
where datum >= :Eingabedatum and datum < :Eingabedatum + 1
Group by FahrerNr, Name;


Unsuccessful execution caused by a system error that precludes
successful execution of subsequent statements.
Dynamic SQL Error.
expression evaluation not supported.
--------------------------------------------------------------
SQLCODE: -902
GDSCODE: 335544569
Holger Klemt
www.ibexpert.com - IBExpert GmbH
Oldenburger Str 233 - 26203 Wardenburg - Germany
IBExpert and Firebird Power Workshops jederzeit auch als Firmenschulung
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.458 Beiträge
 
Delphi 7 Professional
 
#16

AW: SQl Abfrage sehr langsam

  Alt 26. Jun 2024, 11:44
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 .

Geändert von Delphi.Narium (26. Jun 2024 um 23:27 Uhr) Grund: Fehler korrigiert, keine Ahnung, ob ich alle erwischt habe :-(; 'ne noch einen gefunden :-(
  Mit Zitat antworten Zitat
tkhandel

Registriert seit: 2. Jan 2022
Ort: Arnsberg im Sauerland
84 Beiträge
 
Delphi 10.4 Sydney
 
#17

AW: SQl Abfrage sehr langsam

  Alt 26. Jun 2024, 12:17
Versuch 1 klappt, bei Versuch 2 kennt er Zahlart nicht auch wenn ich tu. davor setze nicht
Jürgen
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.458 Beiträge
 
Delphi 7 Professional
 
#18

AW: SQl Abfrage sehr langsam

  Alt 26. Jun 2024, 12:45
Da in dem Select, das den Namen TU erhält, keine Zahlart enthalten ist, kann es auch keine tu.Zahlart geben.

In welcher Tabelle steht denn die Zahlart? Könntest Du uns bitte die Tabellendefinitionen zur Verfügung stellen. Ohne die ist es eine furchtbare Sucherei mit recht geringen Erfolgschancen.

Wenn Zahlart in der Tabelle Tagesumsatz steht, muss das innere SQL so aussehen:
SQL-Code:
    select -- Bitte hier alle Spalten aufführen, die aus der Tabelle Tagesumsatz benötigt werden
      FahrerNr,
      VKBG,
      Zahlart
    from Tagesumsatz
    where Datum between :EingabeDatumVon and :EingabeDatumBis
Vermutlich muss es dann mit demhier weitergehen:
SQL-Code:
 select -- FahrerNr, Name und Umsatz nach Zahlart separieren
    tu.FahrerNr,
    b.Name,
    tu.VKBG as Umsatz,
    case when tu.Zahlart = 1 then tu.VKBG else 0 end as Bar,
    case when tu.Zahlart = 3 then tu.VKBG else 0 end as Karte,
    case when tu.Zahlart = 2 then tu.VKBG else 0 end as LS
  from (
    select -- uns interessieren nur die Daten zum EingabeDatum
      FahrerNr,
      VKBG,
      Zahlart
    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
Die dritte Variante könnte dann dashier werden:
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
    tu.FahrerNr,
    b.Name,
    tu.VKBG as Umsatz,
    case when tu.Zahlart = 1 then tu.VKBG else 0 end as Bar,
    case when tu.Zahlart = 3 then tu.VKBG else 0 end as Karte,
    case when tu.Zahlart = 2 then tu.VKBG else 0 end as LS
  from (
    select -- uns interessieren nur die Daten zum EingabeDatum
      FahrerNr,
      VKBG,
      Zahlart
    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;

Geändert von Delphi.Narium (26. Jun 2024 um 23:25 Uhr) Grund: Schreibfehler, Syntaxfehler im dritten SQL behoben
  Mit Zitat antworten Zitat
tkhandel

Registriert seit: 2. Jan 2022
Ort: Arnsberg im Sauerland
84 Beiträge
 
Delphi 10.4 Sydney
 
#19

AW: SQl Abfrage sehr langsam

  Alt 26. Jun 2024, 21:56
Hallo nee geht auch nicht hier mal die Tabellenstruktur:

1. Tabelle Fahrer (enthält die Liste der Verkaufsfahrer (derzeit 10 maximal 100 Datensätze)
SQL-Code:
 Create TABLE FAHRER (
    ID VARCHAR(60) NOT NULL,
    NR INTEGER,
    ANREDE VARCHAR(10),
    VORNAME VARCHAR(60),
    NAME VARCHAR(60),
    STRASSE VARCHAR(60),
    PLZ VARCHAR(5),
    ORT VARCHAR(60),
    TELEFON_1 VARCHAR(20),
    TELEFON_2 VARCHAR(20),
    MAIL VARCHAR(120)
) ALTER TABLE FAHRER ADD PRIMARY KEY (ID);
2. Tabelle Tagesumsatz (enthält eine Liste der Verkäufe aller Fahrer kommt aus den Kassen)
(30-50 Datensätze je Fahrer je Verkaufstag)

SQL-Code:
CREATE TABLE TAGESUMSATZ (
    ID VARCHAR(60) NOT NULL,
    TOURID VARCHAR(60),
    KUNDEID VARCHAR(60),
    FAHRERID VARCHAR(1),
    FAHRERNR INTEGER,
    BELEGNR VARCHAR(20),
    DATUM TIMESTAMP,
    ZAHLART INTEGER,
    VKNG DOUBLE PRECISION,
    VKBG DOUBLE PRECISION,
    MWST1 DOUBLE PRECISION,
    MWST2 DOUBLE PRECISION,
    ABGEBUCHT BOOLEAN,
    MARGE DOUBLE PRECISION
); ALTER TABLE Tagesumsatz ADD PRIMARY KEY (ID);
Jürgen

Geändert von mkinzler (27. Jun 2024 um 06:34 Uhr) Grund: SQL-Tags ergänzt
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.458 Beiträge
 
Delphi 7 Professional
 
#20

AW: SQl Abfrage sehr langsam

  Alt 26. Jun 2024, 23:26
Was genau geht nicht? Das erste SQL? Das zweite SQL? Das dritte SQL?

Ergeben alle einfach nur kein Ergebnis oder gibt es eine (oder mehrere) Fehlermeldung(en)?

Wenn es Fehlermeldungen gibt, wie lauten sie?

Im dritten SQL muss es am Anfang Name und nicht b.Name heißen.

Dann läuft das SQL bei mir unter FireBird 3.

Habe den Fehler oben behoben.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 4     12 34      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:22 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz