Datum aus einer KW ermitteln

ny_unity

SQL-Guru
Beiträge
201
Hallo zusammen,

ich habe in meiner Datenbank Zeitangaben von Jahr, Monat, Woche und Kalenderwoche, wohingegen der Wert Woche angibt, die wie vielte Woche eines Monats ist.

Am Beispiel Jahr = 2019, Monat = 3, Woche = 1 und KW=9.

Also Datum müsste ich jetzt 01.03.2019, 02.03.2019 und den 03.03.2019 erhalten.

Ich möchte allerdings nur Tage von Montag bis Freitag haben, also im obigen Beispiel nur den 01.03.2019 haben.

Ist das möglich?

Vielen Dank,

Erik
 
Werbung:
Also eigentlich würde ich mir jetzt das Datum nehmen und gucken ob es sich um einen Wochentag handelt. Weil du kein Datum speicherst sondern einen Wust aus Werten die daraus per Funktion eigentlich leicht zu ermitteln wären, müsstest du aus diesen Werten auf das Datum schließen, aber da kommen jetzt natürlich mehrere konkrete Tage in Frage. Ist das bewusst so unscharf? Kannst du nicht vielleicht einfach das Datum speichern?
Code:
DECLARE   @jahr SMALLINT = 2019,
       @monat TINYINT = 3,
       @kw TINYINT = 9,
       @erster_tag_jahr DATE,
       @ein_tag_in_kw DATE,
       @erster_tag_kw DATE

SET       @erster_tag_jahr = convert(DATE,convert(CHAR(4),@jahr) + '-01-01')
SET       @ein_tag_in_kw = dateadd(week,@kw-1,@erster_tag_jahr)
SET       @erster_tag_kw = dateadd(day,-1*(datepart(dw,@ein_tag_in_kw)-1),@ein_tag_in_kw);

WITH tabelle(jahr,monat,kw,erster_tag_kw,datum) AS (
   SELECT   @jahr,@monat,@kw,@erster_tag_kw,@erster_tag_kw
   UNION ALL
   SELECT   jahr,
           monat,
           kw,
           erster_tag_kw,
           dateadd(day,1,datum)
   FROM   tabelle
   WHERE   dateadd(day,1,datum) < dateadd(day,7,erster_tag_kw)
   )
SELECT   jahr,monat,kw,datum
FROM   tabelle
WHERE   datepart(year,datum) = jahr
AND       datepart(month,datum) = monat
AND       datepart(week,datum) = kw
AND       datepart(dw,datum) BETWEEN 1 AND 5
Der erste Select im WITH holt alle Datensätze aus der Ursprungstabelle. Die Spalte "erster_tag_kw" muss natürlich berechnet werden, so wie der Wert bei mir zuvor berechnet wird. Das kann als eigene Funktion passieren oder du ballerst das in eine lange Formel im Select. Dann sind aber Teile doppelt zu berechnen und es wird sehr unübersichtlich, daher habe ich es hier zuvor in Schritten gemacht.

2te Select im WITH-Teil zählt dann Rekurisv hoch, so das alle Tage der betroffenen Woche ausgegeben werden.

Abschließend filterst du alles was du brauchst aber es können natürlich immernoch mehr als ein Tag ausgegeben werden, das währen dann mehrere Zeilen. Wie du damit verfahren willst hast du nicht geschrieben.

Bitte noch beachten:
SET DATEFIRST (Transact-SQL) - SQL Server
 
Kannst du nicht vielleicht einfach das Datum speichern?

Das kennt er ja nicht. Henne-Ei-Problem.

Mal so als gerade-aus-Lösung in PG:

Code:
test=*# with week as (select '2019-03-01'::date + (1-1) * '1week'::interval d), days as (select generate_series(week.d, week.d + '1 week'::interval,'1day'::interval)::date d from week) select * from days where extract(dow from d) between 1 and 5 and extract(week from days.d) = 9;
     d     
------------
 2019-03-01
(1 row)

test=*#

Ich habe hier die Variablen in die Berechnung hart reingeschrieben, das müßte an sich die Applikation machen.
 
Hallo,

danke für Eure Antworten, leider war ich gesundhetlich lange ausgefallen und muss mich erst wieder einarbeiten... @akretschmer, kannst du mir das ganze auch erklären? Ich müsste es ja auf MS SQL anpassen.

danke!

erik
 
Die Abfrage von @ukulele liefert nahezu mein Ergebnis. Ich vergas zu erwähnen, dass ich alle Tage eines Monats bis zur aktuellen Woche haben möchte, also für heute (KW16), möchte ich aus April die KW14, 15 und 16 haben.

Leider bekomm ich das von @ukulele nicht ensprechend umgebastelt.... Gibts noch n Tipp dazu?
 
Werbung:
Natürlich.

Aus
Code:
WHERE   dateadd(day,1,datum) < dateadd(day,7,erster_tag_kw)
wird zunächst mal
Code:
WHERE   dateadd(day,1,datum) <= getdate()
(eventuell musst du dir noch MAX RECURSION anschauen, je nachdem wieviele Tage du maximal hoch zuählst)

Und
Code:
WHERE   datepart(year,datum) = jahr
AND       datepart(month,datum) = monat
AND       datepart(week,datum) = kw
AND       datepart(dw,datum) BETWEEN 1 AND 5
muss natürlich auch sinnhaft angepasst werden, möglicherweise so
Code:
WHERE   datepart(year,datum) >= jahr
AND       datepart(month,datum) >= monat
AND       datepart(week,datum) >= kw
AND       datepart(dw,datum) BETWEEN 1 AND 5
 
Zurück
Oben