SQL-Befehl für Umsatzauswertung für den laufenden Monat

kev2066

Neuer Benutzer
Beiträge
2
Guten Tag zusammen,

ich habe derzeit eine Herausforderung, die ich mit meinem erlernten SQL-KnowHow aus 5 Monaten nicht gelöst bekomme.
Wir haben eine Integrationsplattform, über die wir Auswertungen automatisieren und das bewusst ohne ein BI oder ähnliches anzubinden.

Ich suche nach einem SQL-Befehl, wie ich eine Auswertung zu jedem Datum eines Monats starten kann.
Wir haben das Glück, das unsere Umsätze planbar sind, aufgrund von Vertragsleistungen und -komponenten.
Das heißt wir wissen heute schon, was nächste Woche fakturiert werden kann - zumindest zu 95%.

Folgender Bedarf besteht:
Auswertung wird bspw. am 15.02.2022 angeworfen
Der SQL Befehl soll mir die Umsätze und die geplanten Vertragsleistungen herausziehen, für den laufenden Monat.
Dabei soll, anhand von einem SQL Befehl selbstständig der aktuelle Monat erkannt werden und in diesem Fall vom 01.02.2022 bis 28.02.2022 die Werte raus ziehen.
Da wir Monate haben mit die unterschiedlich lange gehen und bspw. in einem Schaltjahr das ganze auch noch mal anders aussieht,
habe ich für mich überlegt wie folgt vorzugehen.

1) Ermitteln des heutigen Tages (Bspw. 15.02.2022)
2) Festlegung des Monatsanfanges (Bspw. 01.02.2022) [Monatsanfang ist ja statisch, immer der 01...]
3) Plus einen Monat rechnen (Bspw. 01.03.2022)
4) Minus einen Tag rechnen (Bspw. 28.02.2022)

Auf diesem Weg komme ich immer, egal wie viele Tage welcher Monat hat, auf den Monats-letzten.

Jetzt der Punkt an dem ich scheitere, wie verpacke ich das in SQL?

Zweite Frage die sich daraus Resultiert:
Die gleiche Auswertung soll auch immer für den Vormonat und das laufende Jahr kumuliert zur Verfügung stehen.
Wie ich diese beide Anforderungen in SQL verpacke, bekomme ich leider auch nicht hin.


Ich habe viel Zeit in Google gesteckt, auch hier das Forum gewälzt, leider habe ich nichts brauchbares gefunden.
Kann mir jemand dabei helfen?
Dafür wäre ich wirklich sehr dankbar !

Im Voraus vielen Dank für eure Unterstützung.
 
Werbung:

dabadepdu

Datenbank-Guru
Beiträge
1.050
Schau Dir die Funktion
EOMONTH ( start_date , month_to_add )
an. Es gibt sicher alles was man braucht, um ausgehend von einem beliebigen (z.B. Tagesdatum) die weiteren Grenzwerte zu berechnen.

Zyklischer Aufruf geht in MS über Taskplaner bzw. das Pendant in MS SQL selbst.
 

ukulele

Datenbank-Guru
Beiträge
4.702
Zur Ausführung:
Du kannst mit dem Server Agent wiederkehrende Tasks planen. Den gibt es allerdings nicht in SQL Express. Du kannst aber auch immer über einen Windows Task einen Befehl absetzen. Auf jeden Fall wenn du xp_cmdshell am SQL Server aktivierst, und du dann über die CMD einen Befehl absetzen kannst. Ich vermute es geht auch ohne xp_cmdshell übr PowerShell aber sicher bin ich da nicht.

Der Task führt eine stored procedure aus, darin verpackst du dein ganzes SQL.

SQL Code:
Für aktuelles Datum gibt es getdate(), in Ableitungen davon kann man immer first of month oder last of month finden, das gibt es tonnenweise bei Google, hier mal auf die Schnelle:
Code:
SELECT    eomonth(getdate()) AS ende,
        dateadd(month,-1,dateadd(day,1,eomonth(getdate()))) AS anfang
Einzig eine Sache solltest du nicht tun: "Monatsanfang ist ja statisch, immer der 01...", zerlege nicht einen Datumswert unnötig in eine Zeichenkette, setze da eine 1 ein und konvertiere wieder zum Datum. Das ist nicht elegant und sehr fehleranfällig, z.B. wenn sich die Sprache des SQL Servers mal ändert und ein Monat mal nicht mehr an der selben stelle steht.

Du kannst dann im Anschluss an deine Auswertung die Variablen direkt auf einen Vormonat setzen und den Code damit gleich nochmal ausführen.
 
Werbung:

dabadepdu

Datenbank-Guru
Beiträge
1.050
Einzig eine Sache solltest du nicht tun: "Monatsanfang ist ja statisch, immer der 01...", zerlege nicht einen Datumswert unnötig in eine Zeichenkette, setze da eine 1 ein und konvertiere wieder zum Datum. Das ist nicht elegant und sehr fehleranfällig
Das kann ich nur fett unterstreichen!
Da Du schreibst, Du hast erst vor ein paar Monaten angefangen, das gleiche noch mal genereller:
Nimm diesen Datentyp Date (Timestamp und ähnliche) ernst und begreife die Möglichkeiten. Als Hilfestellung dazu: die allermeisten DB können mit diesen Datentypen rechnen, einige sogar schlicht mit den gewohnten Operatoren +, -, .., (was ich persönlich ziemlich cool und intuitiv finde), ansonsten gibt es DB spezifisch eine Fülle von "DATE/TIME" -Funktionen (EOMONTH ist eine davon), entsprechend sind diese Datentypen überall vergleichbar mit den gewohnten Operatoren >,<, >= sowie dem Bereichsvergleich BETWEEN x AND y. Eine weitere "Spezialität" in dieser Ecke: Es macht allermeist nie Sinn, Datum und Uhrzeit in getrennten Spalten zu behandeln. Die meisten DATE/TIME Typen beherrschen beides in Einem, ebenso die zugehörigen Vergleichs- und Rechenoperationen.
Und noch genereller, die Nutzung eines originalen Feldwertes (diesmal unabhängig, ob vom Typ Date oder andere) ist die notwendige Voraussetzung für die Anwendbarkeit eines Index, sofern er auf der Spalte definiert ist. Jede Zerlegung oder Funktion über diese Spalte macht das zunichte. Du kannst den Index dann genausogut löschen und Platz auf der Platte sparen, es macht keinen Performanceunterschied. (In der Realität gibt es Ausnahmen davon, die Dich allerdings nicht jucken müssen, solange Dir die Zusammenhänge nicht klar sind. Betrachte das Vorgehen als goldene Faustregel.)

Fazit:
Für eine Datumsfilterung in einer Datenmenge benutzt Du zwar Funktionen wie EOMONTH, aber NICHT so(!):
..where eomonth(<meineDatumsspalte>)="28.02.2022" and <andereBedingungen>
Das verletzt nicht nur die Hinweise zur Indexnutzung von oben, es beinhaltet auch eine implizite Datumskonvertierung, mit der Chance (besonders im Schaltjahr), das selbstgewählte Monatsende zu "verfehlen" und auch noch einen Formatfehler zu produzieren, wenn die implizite Datumskonvertierung wegen anderer Locale Settings nicht funktioniert.

lieber so:
.. where <meineDatumsspalte> = eomonth(<meinSteuerdatum>) *
.. where <meineDatumsspalte> = eomonth(getdate())
oder typischer bei Filterung auf einen bestimmten Monat (jedes mögliche Datum im Zeitraum des Monats)
.. where <meineDatumsspalte> between dateadd(day, 1, eomonth(<meinSteuerdatum>, -1)) **

* meinSteuerdatum steht für irgendein Datumswert, der treibend für die Abfrage ist, oftmals ist schlicht das aktuelle Datum, bei Auswertungen über aktuelle Zeiträume.
** hier siehst Du, was ich mit Rechnen meinte. Zudem zeigt es, wie die eigentliche Datumsspalte vollkommen unangetastet bleibt (Index bleibt nutzbar). Und nochmal: Enthält die Datumsspalte dabei auch die Uhrzeit, bleibt diese Prüfung voll gültig und Du erwischt auch den letzten Datensatz am 28.2.2022 23:59:23.123, ebenso wie wenn die Uhrzeit in der Spalte fehlte.
 
Oben