Blog programisty w Oracle PL/SQL

Jest to blog eksperymentatora programisty w PL/SQL dla Oracle. Wszystkie kody tutaj zamieszczone mogą być dowolnie wykorzystywane i zmieniane. A jeśli Ktoś z Gości znajdzie błąd, będę niezwykle wdzięczny...
Zapisz

Szukaj na tym blogu

poniedziałek, 28 grudnia 2015

Kalendarz na rok 2016 napisany dla bazy w wersji 12c

Poniżej jest kolejny przykład wykorzystania klauzuli model w wersji iteracyjnej, tym razem do wygenerowania kalendarza z uwzględnieniem świąt i dni roboczych na rok 2016. Jest zdefiniowany jeden wymiar oraz cztery miary: data, nazwa dnia tygodnia, nazwa święta obchodzonego w danym dniu oraz informacja, czy dany dzień jest roboczy.
Dodatkowo został przedstawiony sposób tworzenia funkcji nieskładowanych definiowanych jedynie na potrzeby SQL. To jest bardzo wygodne rozwiązanie,  bo upraszcza składnię zapytań,  zamiast komplikować składnię zapytania, niektóre fragmenty czytelniej jest przenieść do funkcji - np. kiedy byśmy chcieli napisać ogólny algorytm obliczania świąt ruchomych,  to moim zdaniem lepiej umieścić go w procedurze Fdb_JestSwieto.
Przy pisaniu zapytania położyłem większy nacisk na czytelność niż wydajność..




WITH FUNCTION Fdb_JestSwieto(pd_dt DATE) RETURN VARCHAR2 AS
pn_Month NUMBER;
pn_Day NUMBER;
BEGIN
   pn_Day := EXTRACT (DAY FROM pd_dt);
   pn_Month := EXTRACT (MONTH FROM pd_dt);
  IF pn_Month = 1 AND pn_Day =1 THEN
    RETURN 'Nowy Rok';
  ELSIF pn_Month = 1 AND pn_Day =6 THEN
    RETURN 'Święto Trzech Króli' ;
  ELSIF pn_Month = 3 AND pn_Day =27 THEN
    RETURN 'Wielkanoc' ;
  ELSIF pn_Month = 3 AND pn_Day =28 THEN
    RETURN 'Poniedziałek Wielkanocny';
  ELSIF pn_Month = 5 AND pn_Day =1 THEN
    RETURN 'Święto Pracy';
  ELSIF pn_Month = 5 AND pn_Day =3 THEN
    RETURN 'Święto Konstytucji 3 Maja';
  ELSIF pn_Month = 5 AND pn_Day =15 THEN
    RETURN 'Zielone Świątki';
  ELSIF pn_Month = 5 AND pn_Day =26 THEN
    RETURN 'Boże Ciało';
  ELSIF pn_Month = 8 AND pn_Day =15 THEN
    RETURN 'Wniebowzięcie NMP';
  ELSIF pn_Month = 11 AND pn_Day =1 THEN
    RETURN 'Wszystkich Świętych';
  ELSIF pn_Month = 11 AND pn_Day =11 THEN
    RETURN 'Święto Niepodległości';
  ELSIF pn_Month = 12 AND pn_Day IN (25, 26) THEN
    RETURN 'Boże Narodzenie'; 
  END IF;
   RETURN NULL;
END;
SELECT                                                   
    DZIEN , DZIEN_TYGODNIA, SWIETO,
    DZIEN_ROBOCZY
  FROM   (SELECT   0 a  FROM DUAL)
MODEL
   DIMENSION BY (0 lp)
   MEASURES (TO_DATE('2016-01-01', 'YYYY-MM-DD') DZIEN,
CAST(NULL AS VARCHAR2(30 CHAR)) SWIETO,
CAST(NULL AS VARCHAR2(30 CHAR)) DZIEN_TYGODNIA,
    CAST( NULL AS NUMBER(1)) DZIEN_ROBOCZY  )
   RULES
      ITERATE (10000000) UNTIL ( ITERATION_NUMBER = 365)
      (
        DZIEN[ ITERATION_NUMBER ] = DZIEN[0] + ITERATION_NUMBER,
        SWIETO[ ITERATION_NUMBER ] = Fdb_JestSwieto( DZIEN [ ITERATION_NUMBER ]),
        DZIEN_TYGODNIA[ ITERATION_NUMBER ] = TO_CHAR(DZIEN [   ITERATION_NUMBER ], 'DAY'),
        DZIEN_ROBOCZY [ ITERATION_NUMBER ] = CASE  WHEN SWIETO [ ITERATION_NUMBERIS NOT NULL OR TO_CHAR(DZIEN [ ITERATION_NUMBER ], 'D') IN ('6','7')
         THEN 0
          ELSE 1
       END
      )