Neu SQL Abfrage aus mehreren Tabellen

marfitec

Aktives Mitglied
10. März 2018
86
14
Hallo Zusammen,

ich habe aktuell einen Denkfehler / Verständnisfehler und hoffe das mir von euch jemand weiterhelfen kann.

Folgende Abfrage generiert für jede Position der Bestellung eine neue Zeile. Ich wollte aber nur eine Zeile pro Rechnung.

Wo habe ich den Gedankenfehler?

Code:
SELECT trechnung.dErstellt, trechnung.cRechnungsNr, tZahlung.cExternalTransactionId, tBestellung.cInetBestellNr, tAdresse.cName, tZahlung.cName  FROM trechnung

INNER JOIN tBestellung ON trechnung.tBestellung_kBestellung = tBestellung.kBestellung

INNER JOIN tZahlung ON tZahlung.kBestellung = tBestellung.kBestellung

INNER JOIN tAdresse ON tAdresse.kKunde = tBestellung.tKunde_kKunde

WHERE trechnung.dErstellt BETWEEN  CONVERT(DATETIME,'01.11.2019', 104) AND CONVERT(DATETIME,'30.12.2019', 104)
Grüße
Marcus
 

sjk

Gut bekanntes Mitglied
16. Januar 2019
188
64
Moin Marcus,

läuft das SQL in einem Berichtscontainer einer L&L Vorlage oder an einem anderen Ort?
 

waagenwelt

Aktives Mitglied
30. September 2012
64
2
Toppenstedt
Hallo Marcus,

nein, tut sie nicht. ;)

Wenn ein Kunde mehrere Adressen hat, so erzeugt die Abfrage entsprechend viele Zeilen je Rechnung.
Das gleiche gilt für Zahlungen pro Rechnung und multipliziert sich sogar.

Ich würde auf tBestellung.kRechnungsadresse statt auf tBestellung.tKunde_kKunde joinen und eine Summe über die Zahlungen bilden.

Viele Grüße

Stefan
 

marfitec

Aktives Mitglied
10. März 2018
86
14
Hallo.

vielen Dank für die schnellen Rückmeldungen.

@sjk
Die Abfrage ist ein normales query im SQL Manager. Ich teste da nur, ob meine Abfrage das gewünschte Ergebnis bringt. (tut es ja nicht :) )

@waagenwelt
Auf die Rechnungsadresse zu verbinden ist ein gute Idee, die gibt es dann ja nur einmal.
Zahlungen gibt es meistens nur eine pro Rechnung. (Berücksichtigen müsste ich das aber auch noch)

Eventuell ist es doch einfacher, die Abfragen zu trennen.

Das Ganze läuft später in einer C# Anwendung. (verstehe ich wesentlich besser als SQL :D)

Grüße
Marcus
 

somobil

Mitglied
19. Dezember 2019
38
4
Der "Denkfehler" ist der, dass der Query alle Positionen ausgibt, so wie du es auch "verlangt" hast.

Was noch fehlt ist die Zusammenfassung nach Rechnung, also ein "

SQL:
GROUP BY trechnung.cRechnungsNr
 

marfitec

Aktives Mitglied
10. März 2018
86
14
@somobil

Vielen Dank für deine Antwort. Wie du richtig erkannt hast, handelt es sich ehr um Verständnisprobleme als um Denkfehler ;)
Leider sind Computer dumm und tun genau das was man ihnen sagt :D

Das Einfügen der GROUP Funktion führt nun zu einer Fehlermeldung die ich mit meinem aktuellen Wissensstand nicht beheben kann.

Meldung 8120, Ebene 16, Status 1, Zeile 1
Die trechnung.dErstellt-Spalte ist in der Auswahlliste ungültig, da sie nicht in einer Aggregatfunktion und nicht in der GROUP BY-Klausel enthalten ist.

Behebung:
Fehler der Ebene 16 sind Fehler, die vom Anwender hervorgerufen werden. Sie können und müssen vom Anwender korrigiert werden. Das Statement kann so nicht ausgeführt werden. Die Spalte muss entweder in einer Aggregatfunktion enthalten sein oder in der GROUP BY Klausel.
Hast du einen Buch-Tipp für mich, damit ich mich mit dem Thema SQL Server näher beschäftigen kann?

SQL:
SELECT trechnung.dErstellt, trechnung.cRechnungsNr, tZahlung.cExternalTransactionId, tBestellung.cInetBestellNr, tAdresse.cName, tZahlung.cName  FROM trechnung

INNER JOIN tBestellung ON trechnung.tBestellung_kBestellung = tBestellung.kBestellung

INNER JOIN tZahlung ON tZahlung.kBestellung = tBestellung.kBestellung

INNER JOIN tAdresse ON tAdresse.kKunde = tBestellung.tKunde_kKunde

WHERE trechnung.dErstellt BETWEEN  CONVERT(DATETIME,'01.11.2019', 104) AND CONVERT(DATETIME,'30.12.2019', 104)

GROUP BY trechnung.cRechnungsNr
Hier die vermutlich sinnbefreite Umgehung des Problems
SQL:
SELECT MIN(trechnung.dErstellt) AS "Datum", 
         trechnung.cRechnungsNr AS "Rechnungsnummer", 
         MIN(tZahlung.cExternalTransactionId) AS "Externe Transaktions ID", 
         MIN(tBestellung.cInetBestellNr) AS "Externe Bestellnummer", 
         MIN(tAdresse.cName) AS "Nachname", 
         MIN(tZahlung.cName) AS "Zahlungsname"  
         
FROM trechnung

INNER JOIN tBestellung ON trechnung.tBestellung_kBestellung = tBestellung.kBestellung

INNER JOIN tZahlung ON tZahlung.kBestellung = tBestellung.kBestellung

INNER JOIN tAdresse ON tAdresse.kKunde = tBestellung.tKunde_kKunde

WHERE trechnung.dErstellt BETWEEN  CONVERT(DATETIME,'01.11.2019', 104) AND CONVERT(DATETIME,'30.12.2019', 104)

GROUP BY trechnung.cRechnungsNr
Grüße
Marcus
 
Zuletzt bearbeitet:

Eiko

Aktives Mitglied
26. Juni 2017
56
2
@somobil

Vielen Dank für deine Antwort. Wie du richtig erkannt hast, handelt es sich ehr um Verständnisprobleme als um Denkfehler ;)
Leider sind Computer dumm und tun genau das was man ihnen sagt :D

Das Einfügen der GROUP Funktion führt nun zu einer Fehlermeldung die ich mit meinem aktuellen Wissensstand nicht beheben kann.


Grüße
Marcus
MMn, wenn du GROUP BY einfügst, musst du alle ausgewählten Spalten gruppieren.
Also:

SQL:
GROUP BY trechnung.cRechnungsNr, trechnung.dErstellt, tZahlung.cExternalTransactionId, tBestellung.cInetBestellNr, tAdresse.cName, tZahlung.cName
 

marfitec

Aktives Mitglied
10. März 2018
86
14
Hallo @Eiko,

vielen Dank für deine Antwort. Mit den o.g. MIN Funktionen hat es zwar auch geklappt, aber dein Hinweis gefällt mir wesentlich besser :)

Vielen Dank dafür.

Grüße
Marcus
 

marfitec

Aktives Mitglied
10. März 2018
86
14
Leider habe ich noch mal eine Frage. Und zwar wird der VKPreis mehrmals summiert. Scheint immer doppelt zu sein.

Was mache ich falsch?

SQL:
SELECT FORMAT(MIN(trechnung.dErstellt),'dd.MM.yyyy') AS "Datum",trechnung.cRechnungsNr AS "Rechnungsnummer",
                FORMAT(SUM(tbestellpos.fVKPreis),'#,0.00') AS "Preis",
                MIN(tZahlung.cExternalTransactionId) AS "Externe Transaktions ID", MIN(tBestellung.cInetBestellNr) AS "Externe Bestellnummer",
                CONCAT(CONCAT(MIN(tAdresse.cVorname), ' '), MIN(tAdresse.cName)) AS "Name",
                MIN(tZahlung.cName) AS "Zahlungsname"  FROM trechnung INNER JOIN tBestellung ON trechnung.tBestellung_kBestellung = tBestellung.kBestellung
                INNER JOIN tZahlung ON tZahlung.kBestellung = tBestellung.kBestellung INNER JOIN tAdresse ON tAdresse.kKunde = tBestellung.tKunde_kKunde
                INNER JOIN tbestellpos ON tbestellpos.tBestellung_kBestellung = tRechnung.tBestellung_kBestellung
                WHERE trechnung.dErstellt BETWEEN  CONVERT(DATETIME,'01.02.2020', 104) AND CONVERT(DATETIME,'02.02.2020', 104) GROUP BY trechnung.cRechnungsNr
 

marfitec

Aktives Mitglied
10. März 2018
86
14
Für die Nachwelt. Das Problem war, wie @waagenwelt schon geschrieben hatte, die Adresse. Ich hatte immer noch die Kundennummer statt der Rechnungsadresse im join. Dadruch wurde es multipliziert. (Wer Empfehlungen umsetzen kann, ist klar im Vorteil :D) Danke noch mal!

SQL:
SELECT FORMAT(MIN(trechnung.dErstellt),'dd.MM.yyyy') AS "Datum",MIN(trechnung.cRechnungsNr) AS "Rechnungsnummer",
                FORMAT(SUM(tbestellpos.fVKPreis*tBestellpos.nAnzahl),'#,0.00')  AS "Preis",
                MIN(tZahlung.cExternalTransactionId) AS "Externe Transaktions ID",
                MIN(tBestellung.kBestellung) AS "Externe Bestellnummer",
                CONCAT(CONCAT(MIN(tAdresse.cVorname), ' '), MIN(tAdresse.cName)) AS "Name",
                MIN(tZahlung.cName) AS "Zahlungsname"  FROM trechnung
                INNER JOIN tBestellung ON trechnung.tBestellung_kBestellung = tBestellung.kBestellung
                INNER JOIN tZahlung ON tZahlung.kBestellung =  tBestellung.kBestellung
                INNER JOIN tAdresse ON tBestellung.kRechnungsAdresse = tAdresse.kAdresse
                INNER JOIN tbestellpos ON tbestellpos.tBestellung_kBestellung = tBestellung.kBestellung
                WHERE trechnung.dErstellt BETWEEN  CONVERT(DATETIME,'01.02.2020', 104) AND CONVERT(DATETIME,'02.02.2020', 104)
                GROUP BY trechnung.cRechnungsNr
Doppler habe ich jetzt immer noch drin. Dieses Problem sollte ich aber auch noch lösen können ... hoffe ich :)

EDIT: kRechnungsAdresse hat eine komplett andere nummer als KKunde.Adresse

Edit2:
INNER JOIN tAdresse ON tAdresse.kAdresse = tBestellung.tAdresse_kAdresse geht auch nicht, da dann die Amazon Bestellungen nicht gefunden werden.

Mir erschließen sich die Adressen gerade nicht ...

Edit3:
trechnungsadresse ist eine ganz andere Tabelle, deshalb konnte ich tBestellung.kRechnungsAdresse nicht mit den Adressen joinen. Mit trechnungsadresse klapp es jetzt aber wunderbar.
 
Zuletzt bearbeitet:

zwitsch

Gut bekanntes Mitglied
14. November 2007
314
17
Schau mal bei den Views nach. Dort gibt es die Kunde.vRechnungen (oder so ähnlich, Wawi steht gerade nicht zur Verfügung). Dort findest Du vielleicht die Informationen, die Du benötigst, ganz ohne Join.
 

marfitec

Aktives Mitglied
10. März 2018
86
14
Hey @zwitsch,

das ist ja Klasse :). Da kann ich mir diesen Riesen-Hack ja sparen. In die Views habe ich noch nie geguckt. (Hätte ich tun sollen^^)
Da ist alles drin was ich brauche. (und noch mehr)

Das joinen funktioniert jetzt zwar, aber das View sollte noch etwas zügiger sein.

vielen Dank!

Grüße
Marcus
 

marfitec

Aktives Mitglied
10. März 2018
86
14
So einfach kann die Welt sein :D

SQL:
SELECT FORMAT(Kunde.lvRechnungen.dErstellt,'dd.MM.yyyy') AS "Datum",
                Kunde.lvRechnungen.cRechnungsnummer AS "Rechnungsnummer",
                Kunde.lvRechnungen.fRechnungswert  AS "Umsatz",
                Kunde.lvRechnungen.cShopbestellnummer AS "Externe Transaktions ID",
                CONCAT(CONCAT(Kunde.lvRechnungen.cRechnungsadresseVorname, ' '), Kunde.lvRechnungen.cRechnungsadresseNachname) AS "Name",
                (Kunde.lvRechnungen.cZahlungsartname) AS "Zahlungsname" 
                
FROM Kunde.lvRechnungen

WHERE (dErstellt BETWEEN  CONVERT(DATETIME,'01.02.2020', 104) AND CONVERT(DATETIME,'29.02.2020', 104))
 

marfitec

Aktives Mitglied
10. März 2018
86
14
Für Historische Daten scheint das nicht ganz zu funktionieren. Da sind z.B. cShopbestellnummer von ebay leer. Aber ansonsten TOP!