Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Count in SQL mit Left Join (https://www.delphipraxis.net/216590-count-sql-mit-left-join.html)

Hobbycoder 23. Jan 2025 22:19

Datenbank: MariaDB • Version: 11.5.2 • Zugriff über: Zeos 8.0.0

Count in SQL mit Left Join
 
Hi,

ich will die Summen von Artikeln nach Kunden auflisten.
Die Netto/MwSt/Brutto sind nur in der Tabelle Positionen vorhanden. Kundennummer lediglich in der Tabelle Kunden. Es wird alles nur über die Guid's referenziert.
Soweit so gut.

Lediglich bei der Anzahl der Aufträge (Vorgänge) erhalte ich immer die Anzahl der Positionen.
Klar, weil das ja auch so in SQL-Abfrage steht.

Wie könnte ich in dieser Abfrage aber die Anzahl der Vorgänge erhalten?

Code:
SELECT
  SUM(A.Netto) AS Netto, SUM(A.MwSt) AS MwSt, SUM(A.Brutto) AS Brutto, COUNT(B.vorgangsnummer) AS Anzahl, Auftragguid, B.Firmenname, B.kundenguid, C.kundennummer
FROM Positionen AS A
  LEFT JOIN Vorgang AS B ON A.auftragguid=B.guid
  LEFT JOIN Kunden AS C ON B.kundenguid=C.guid
WHERE B.Fakturiert<>0 AND (B.vorgangstype=4 OR B.vorgangstype=5 OR B.vorgangstype=6) AND B.FakturiertAm>='2025-01-01' AND B.FakturiertAm<='2025-01-31'
GROUP BY C.guid ORDER BY SUM(A.netto) DESC;

Delphi.Narium 23. Jan 2025 23:27

AW: Count in SQL mit Left Join
 
Habe das SQL mal umformatiert, damit es für mich lesbarer und etwas verständlicher wird:
SQL-Code:
SELECT
  SUM(A.Netto)           AS Netto,
  SUM(A.MwSt)            AS MwSt,
  SUM(A.Brutto)          AS Brutto,
  COUNT(B.vorgangsnummer) AS Anzahl,
  A.Auftragguid,
  B.Firmenname,
  B.kundenguid,
  C.kundennummer
FROM Positionen AS A
  LEFT JOIN Vorgang AS B ON A.auftragguid = B.guid
  LEFT JOIN Kunden AS C ON B.kundenguid = C.guid
WHERE B.Fakturiert <> 0
AND  B.vorgangstype in (4,5,6)
AND  B.FakturiertAm between '2025-01-01' AND '2025-01-31'
GROUP BY
  C.guid -- Bei Left Join auf Kunden heißt das, dass es nicht zwingend eine C.guid geben muss,
         -- diese also im Ergebnis Null sein kann und alle Sätze ohne Kunden werden dann summiert.
         -- Ist das gewollt?
         -- Mir scheint das zum Gruppieren nicht zwingend geeignet / sinnvoll.
         -- Außerdem scheinen hier noch ein paar Spalten im Group by zu fehlen.
         -- Alles, was nicht aggregiert wird, muss eigentlich ins Group by.
         -- Ist das bei MariaDB anders?
ORDER BY
  1 DESC;
Kann es Positionen geben, zu denen es entweder keinen Vorgang oder keinen Kunden oder weder Vorgang noch Kunden geben kann?
Wenn nein, dann ist der Left-Join hier fehlt am Platz.

Nachfolgend eine Idee, bei der ich nicht davon ausgehe, dass sie auf Anhieb funktioniert. Schreibfehler, Syntaxfehler, Denkfehler ... nicht ausgeschlossen ;-)
SQL-Code:
SELECT
  SUM(Netto) AS Netto,
  SUM(MwSt)  AS MwSt,
  SUM(Brutto) AS Brutto,
  SUM(Anzahl) AS Anzahl,
  Firmenname,
  kundenguid,
  kundennummer
from (
  SELECT
    SUM(A.Netto)           AS Netto,
    SUM(A.MwSt)            AS MwSt,
    SUM(A.Brutto)          AS Brutto,
    1                       AS Anzahl, -- Hier sollte es pro Vorgang einen Satz geben.
    B.GUID,
    B.Firmenname,
    B.kundenguid,
    C.kundennummer
  FROM Positionen AS A
    LEFT JOIN Vorgang AS B ON A.auftragguid = B.guid
    LEFT JOIN Kunden AS C ON B.kundenguid = C.guid
  WHERE B.Fakturiert <> 0
  AND  B.vorgangstype in (4,5,6)
  AND  B.FakturiertAm between '2025-01-01' AND '2025-01-31'
  GROUP BY
    B.GUID,
    B.Firmenname,
    B.Kundenguid,
    C.Kundennummer
) X
GROUP BY
  Firmenname,
  Kundenguid,
  Kundennummer
ORDER BY
  1 DESC, -- Und was ist, wenn es mehrere, identische Nettobeträge gibt?
          -- Reihenfolge dann zufällig?
  5;     -- Firmenname

Hobbycoder 24. Jan 2025 11:47

AW: Count in SQL mit Left Join
 
MEGA :thumb:

Funzt auf Anhieb.
Wofür steht aber in dem Query das X

SQL-Code:
  GROUP BY
    B.GUID,
    B.Firmenname,
    B.Kundenguid,
    C.Kundennummer
) X  -- wofür steht das X?
GROUP BY
  Firmenname,
PS: Nur am info für lesende: In der DB gibt es IMMER zu jedem Datensatz eine GUID und wenn gelöscht wird, dann werden immer auch alle referenzierten Datensätze mit gelöscht

mkinzler 24. Jan 2025 11:55

AW: Count in SQL mit Left Join
 
Zitat:

Wofür steht aber in dem Query das X?
Ist der Alias für die DERIVED TABLE.

Delphi.Narium 24. Jan 2025 11:59

AW: Count in SQL mit Left Join
 
Das X ist der Alias für das äußere Select, statt X kannst Du da auch einen sprechenden Namen hinschreiben.

Eigentlich ist das analog zu
SQL-Code:
FROM Positionen AS A
zu sehen.

Zu Deinem Nachsatz:

Es gibt also keine Positionen ohne Vorgänge und keine Vorgänge ohne Kunden. Dann ändere bitte das Left Join in Inner Join.

Für jemand "fremdes", ohne genaue Kenntnis zum Datenmodel, liest sich das SQL mit Left Join so, als wären eben Positionen ohne Vorgänge möglich und Vorgänge ohne Kunden. Und das ließe den Schluss zu, dass in der Ergebnismenge auch diese Werte summiert / gezählt würden. Fachlich ist das dann aber sehr fraglich und als Prüfer / Tester würde ich sowas bemängeln bzw. die Software nicht abnehmen.

Hobbycoder 24. Jan 2025 13:00

AW: Count in SQL mit Left Join
 
Danke für deine Erläuterung.

Olli73 24. Jan 2025 17:21

AW: Count in SQL mit Left Join
 
Ein
Code:
COUNT(distinct (B.vorgangsnummer)) AS Anzahl,
hätte vielleicht auch funktioniert !?


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:27 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz