平日or土曜日or日祝日を判定するSQL(Oracle)

#1. 作ったもの
ある日付が平日or土曜日or日祝日を判定するsqlを書いたので、ついでにqiitaに上げておこうかと。

#2. 関数本体

```sql:myFunction.sql
CREATE OR REPLACE FUNCTION myFunction(
    IN_DATE DATE
) RETURN VARCHAR2
IS
    RETURN_VARCHAR2 VARCHAR2(8);
BEGIN
    SELECT
        CASE
            WHEN HOLIDAY IS NOT NULL OR DAY_OF_THE_WEEK = '1' THEN
                'HOLIDAY'
            WHEN HOLIDAY IS NULL AND DAY_OF_THE_WEEK = '7' THEN
                'SATURDAY'
            ELSE 'WEEKDAY'
        END WEEKDAY_HOLIDAY
    INTO
      RETURN_VARCHAR2
    FROM (
        SELECT
            TRUNC(IN_DATE) TODAY,
            TO_CHAR(IN_DATE,'D') DAY_OF_THE_WEEK
        FROM
            DUAL) T1
    LEFT OUTER JOIN
        HOLIDAYS
    ON
        T1.TODAY = HOLIDAYS.HOLIDAY;
    RETURN RETURN_VARCHAR2;
EXCEPTION
    WHEN OTHERS THEN
        RAISE;
END;
```

#3. 使い方
##3-1. 事前準備
事前に祝日リストをテーブルに登録してください。
祝日リストデータは[こちら](http://calendar.infocharge.net/cal/2019/)から持ってきました(2018/12/23)が、ご利用の際は手元のカレンダーに従ってください。

```sql:holiday_list.sql
CREATE TABLE HOLIDAYS(
    HOLIDAY DATE
);
INSERT INTO
    HOLIDAYS
SELECT TO_DATE('2019-01-01','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-01-14','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-02-11','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-03-21','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-04-29','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-05-03','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-05-04','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-05-05','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-05-06','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-07-15','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-08-11','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-08-12','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-09-16','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-09-23','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-10-14','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-11-03','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-11-04','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-11-23','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2019-12-23','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2020-01-01','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2020-01-13','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2020-02-11','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2020-03-20','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2020-04-29','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2020-05-03','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2020-05-04','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2020-05-05','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2020-07-20','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2020-08-11','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2020-09-21','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2020-09-22','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2020-10-12','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2020-11-03','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2020-11-23','YYYY-MM-DD') FROM DUAL
UNION ALL
SELECT TO_DATE('2020-12-23','YYYY-MM-DD') FROM DUAL
;
```


##3-2. 実行結果

```sql:exec.sql
SQL> select myfunction(to_date('2018-12-22','YYYY-MM-DD')) A, 
  2         myfunction(to_date('2018-12-23','YYYY-MM-DD')) B, 
  3         myfunction(to_date('2018-12-25','YYYY-MM-DD')) C,
  4         myfunction(to_date('2019-01-01','YYYY-MM-DD')) D
  5  from dual;

A          B          C          D         
---------- ---------- ---------- ----------
SATURDAY   HOLIDAY    WEEKDAY    HOLIDAY   

```

#4. 注意点

* 'TO_CHAR(date, format)'の結果ですが、地域によって異なる可能性があるみたいです。
  [Format Models](https://docs.oracle.com/en/database/oracle/oracle-database/18/sqlrf/Format-Models.html#GUID-DFB23985-2943-4C6A-96DF-DF0F664CED96)
  [日付用の書式モデル](https://www.shift-the-oracle.com/sql/datetime-format-element.html)  

* exceptionも仕込んでありますが、function内で処理は行っていません。呼び出し元で好きに捌いてください。休日テーブルに主キーを貼っておくと安心。
* 祝日リストのメンテは手動です。実際のカレンダーを確認してデータ作成してください。
* ナイスな関数名を思いつきませんでした。いい感じに命名してあげてください。