| 需求 | SQL | 範例結果 |
|---|---|---|
| 季度 | TO_CHAR(sysdate,'Q') | 3 |
| 年 | TO_CHAR(sysdate,'YYYY') | 2024 |
| 月 | TO_CHAR(sysdate,'MM') | 08 |
| 日 | TO_CHAR(sysdate,'DD') | 15 |
| 星期幾 (數字 1-7) | TO_CHAR(sysdate,'D') | 4 |
| 星期名稱 | TO_CHAR(sysdate,'DAY') | THURSDAY |
| 年中天數 (1-366) | TO_CHAR(sysdate,'DDD') | 228 |
| EXTRACT 年/月/日 | EXTRACT(YEAR FROM dt) | 標準 SQL,可用於 Partition Key |
| 需求 | SQL |
|---|---|
| 上個月最後一天 | LAST_DAY(ADD_MONTHS(sysdate,-1)) |
| 本月最後一秒 | TRUNC(ADD_MONTHS(sysdate,1),'MM') - 1/24/60/60 |
| 本週週一 | TRUNC(sysdate,'DAY') + 1 |
| 年初至今天數 | CEIL(sysdate - TRUNC(sysdate,'YEAR')) |
| 今年第幾週 | TO_CHAR(sysdate,'FMWW') |
| 本月第幾週 | TO_CHAR(sysdate,'WW') - TO_CHAR(TRUNC(sysdate,'MM'),'WW') + 1 |
| 本月天數 | TO_CHAR(LAST_DAY(sysdate),'DD') |
| 今年天數 | ADD_MONTHS(TRUNC(sysdate,'YEAR'),12) - TRUNC(sysdate,'YEAR') |
| 下個週一 | NEXT_DAY(sysdate,'MONDAY') |
| 間隔 N 秒/分/時/天/月/年 | sysdate + N/24/60/60 / ADD_MONTHS(sysdate,N) |
| 兩日期間天數 | FLOOR(sysdate - TO_DATE('20020405','YYYYMMDD')) |
CREATE TABLE t (s DATE, e DATE);
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD';
INSERT INTO t VALUES ('2003-03-01','2003-03-03');
INSERT INTO t VALUES ('2003-03-02','2003-03-03');
INSERT INTO t VALUES ('2003-03-07','2003-03-08'); -- 週六~日
INSERT INTO t VALUES ('2003-03-07','2003-03-09'); -- 週六~一
INSERT INTO t VALUES ('2003-03-05','2003-03-07'); -- 週三~五
INSERT INTO t VALUES ('2003-02-01','2003-03-31'); -- 跨月
COMMIT;
SELECT s, e,
(e - s + 1) AS total_days,
(e - s + 1) -
(TRUNC(e) - TRUNC(s) + 1) * 2/7 AS approx_workdays, -- 粗估
-- 精確:逐日展開判斷(需數字表或 CONNECT BY)
(SELECT COUNT(*) FROM
(SELECT TRUNC(s) + LEVEL - 1 dt FROM dual
CONNECT BY LEVEL <= e - s + 1)
WHERE TO_CHAR(dt,'DY','NLS_DATE_LANGUAGE=AMERICAN') NOT IN ('SAT','SUN')
) AS exact_workdays
FROM t;
**原理**:CONNECT BY LEVEL 產生日期序列 → TO_CHAR(dt,'DY') 判斷星期 → 排除 SAT/SUN。
**擴展**:加入假日表 holidays(dt) 進一步排除。
SELECT CASE
WHEN TO_NUMBER(TO_CHAR(sysdate,'HH24')) BETWEEN 6 AND 11 THEN '上午'
WHEN TO_NUMBER(TO_CHAR(sysdate,'HH24')) BETWEEN 11 AND 17 THEN '下午'
WHEN TO_NUMBER(TO_CHAR(sysdate,'HH24')) BETWEEN 17 AND 21 THEN '晚上'
ELSE '深夜'
END AS period
FROM dual;
SELECT * FROM emp ORDER BY hiredate
OFFSET 10 ROWS FETCH NEXT 20 ROWS ONLY; -- 第 11-30 筆
取代傳統 ROWNUM 巢狀查詢,語意清晰、最佳化器支援完善。
CURRENT_TIMESTAMP:Session 時區時間(含時區位移)。SYSTIMESTAMP:資料庫伺服器 OS 時區時間。FROM_TZ(TS, 'TZR'):附加時區資訊。CAST(TS AS TIMESTAMP WITH LOCAL TIME ZONE):自動轉換至 Session 時區。Oracle 日期運算威力在於 **TRUNC/ROUND` 邊界對齊、`ADD_MONTHS` 月份邏輯、`INTERVAL` 語意運算、`CONNECT BY` 日期序列展開**。掌握上述 30 種模式,涵蓋 99% 業務場景。工作日計算以「日期序列 + 星期/假日過濾」為通用模板,靈活擴展。