Datum + Arbeitstage anhand einer Tabelle 'Kalender'

tonyman86

Neuer Benutzer
Beiträge
3
Hallo,

ich habe folgendes Problem. In einer Abfrage möchte ich zu einem Ist-Datum eine Anzahl an Arbeitstagen addieren und ein Plan-Datum zu generieren.

Hierzu habe ich eine Kalender-Tabelle in der alle Daten enthalten sind und mit 1 für Arbeitstag oder 0 für nicht Arbeitstag gekennzeichnet sind.

Wie kann ich diese Abfrage gestalten, dass er anhand meiner Tabelle 'Kalender' das Datum welches 20 Arbeitstage später ist, findet?

Vielen Dank schon einmal.
 
Werbung:
Ich erstelle mir mal eine Tabelle für den Juli, der alle Tage hat und bei Arbeitstagen das mit TRUE anzeigt:

Code:
test=# create table kalender as select ('2015-07-01'::date + s*'1day'::interval)::date as datum, case when extract(dow from ('2015-07-01'::date + s*'1day'::interval)::date) in (0,6) then false else true end as weekday from generate_series(0,30) s;
SELECT 31
test=*#
test=*#
test=*#
test=*# select * from kalender ;
  datum  | weekday
------------+---------
 2015-07-01 | t
 2015-07-02 | t
 2015-07-03 | t
 2015-07-04 | f
 2015-07-05 | f
 2015-07-06 | t
 2015-07-07 | t
 2015-07-08 | t
 2015-07-09 | t
 2015-07-10 | t
 2015-07-11 | f
 2015-07-12 | f
 2015-07-13 | t
 2015-07-14 | t
 2015-07-15 | t
 2015-07-16 | t
 2015-07-17 | t
 2015-07-18 | f
 2015-07-19 | f
 2015-07-20 | t
 2015-07-21 | t
 2015-07-22 | t
 2015-07-23 | t
 2015-07-24 | t
 2015-07-25 | f
 2015-07-26 | f
 2015-07-27 | t
 2015-07-28 | t
 2015-07-29 | t
 2015-07-30 | t
 2015-07-31 | t
(31 rows)


Jetzt ermittle ich alle Arbeitstage ab dem 6. Juli und zähle diese:

Code:
test=*# select *, row_number() over (order by datum) from kalender where datum >= '2015-07-06'::date and weekday;
  datum  | weekday | row_number
------------+---------+------------
 2015-07-06 | t  |  1
 2015-07-07 | t  |  2
 2015-07-08 | t  |  3
 2015-07-09 | t  |  4
 2015-07-10 | t  |  5
 2015-07-13 | t  |  6
 2015-07-14 | t  |  7
 2015-07-15 | t  |  8
 2015-07-16 | t  |  9
 2015-07-17 | t  |  10
 2015-07-20 | t  |  11
 2015-07-21 | t  |  12
 2015-07-22 | t  |  13
 2015-07-23 | t  |  14
 2015-07-24 | t  |  15
 2015-07-27 | t  |  16
 2015-07-28 | t  |  17
 2015-07-29 | t  |  18
 2015-07-30 | t  |  19
 2015-07-31 | t  |  20
(20 rows)

Daraus nun das Datum des z.B. 10 Arbeitstages (10 Tage Urlaub) zu ermitteln überlasse ich Dir zur Übung.
 
Danke, ziemlich genial :)

Habe mir da jetzt eine Funktion draus gebaut.

Code:
create or replace FUNCTION DATEADDWORKDAYS
(cdate in date, cdays in number, cwerk in VARCHAR2)
RETURN DATE
IS
  returndate date;
    cursor c1 is
  SELECT DATUM FROM (SELECT TBL_WERKSKALENDER.DATUM,
  ROW_NUMBER() Over (Order By TBL_WERKSKALENDER.DATUM) AS RW
FROM TBL_WERKSKALENDER
WHERE TBL_WERKSKALENDER.DATUM    > cdate
AND TBL_WERKSKALENDER.WERK       = cwerk
AND TBL_WERKSKALENDER.ARBEITSTAG = 1) 
WHERE RW = cdays;
BEGIN
open c1;
fetch c1 into returndate;
close c1;
IF returndate IS NULL then
RETURN cdate;
ELSE
RETURN returndate;
END IF;
RETURN returndate;
END DATEADDWORKDAYS;

Oder zu kompliziert?
 
Wiso arbeitest du hier freiwillig mit einem Cursor und hast dann mehrere RETURN returndate drin? Ist das nicht überflüssig?
 
Hi,
gute Frage wieso ich mit einem Cursor arbeite. Mit Funktionen selber habe ich noch nicht viel gemacht, also habe ich mir ein Beispiel einer Funktion mit einer SELECT Abfrage aus Google gesucht und diese entsprechend umgebaut. In dieser Funktion war auch der Cursor enthalten. Wie kann ich diese Funktion denn ohne Cursor gestalten?

Zu meinen Returns:
Es kann vorkommen, wenn die zu addierenden Werktage 0 Sind, soll das Ausgangsdatum zurückgegeben werden, ansonsten das ermittelte Datum.
Und das letzte RETURN ist wirklich überflüssig, werde ich löschen, danke :)
 
Werbung:
So ginge es wohl ohne Cursor... Hat aber wirklich 0 Performancegewinn / Whatsoever...
(Wäre auch mein Lösungsweg... Ist aber wirklich nur optisch...)
Code:
Create Or Replace Function dateaddworkdays
(
   cdate In Date,
   cdays In Number,
   cwerk In Varchar2
) Return Date Is
   returndate Date;
Begin
   Select datum
   Into   returndate
   From   (Select tbl_werkskalender.datum
                 ,row_number() over(Order By tbl_werkskalender.datum) As rw
           From   tbl_werkskalender
           Where  tbl_werkskalender.datum > cdate
           And    tbl_werkskalender.werk = cwerk
           And    tbl_werkskalender.arbeitstag = 1)
   Where  rw = cdays;

   Return returndate;

Exception
   When no_data_found Then
      Return cdate;
End dateaddworkdays;
Deswegen verstehe ich die Aussage von @ukulele auch nicht... Wüsste nicht wann man einen Cursor "zwangsweise" anlegen müsste...
Im Gegenteil... Man will sogar Cursor, so viele wie möglich (natürlich im Rahmen weltlicher Logik)...

Edit:

Rein technisch gesehen müsste man auch noch die Exception "TOO_MANY_ROWS" abfangen...
 
Zurück
Oben