我遇到了 Oracle 23c 的奇怪行为。据我了解,ROUND 函数中缺少第二个参数应该与显式放置“DAY”参数完全相同。
SELECT TO_DATE('2024-06-26 15:02:18','YYYY-MM-DD HH24:MI:SS') AS result
, ROUND(TO_DATE('2024-06-26 15:02:18','YYYY-MM-DD HH24:MI:SS') ) AS default_result
, ROUND(TO_DATE('2024-06-26 15:02:18','YYYY-MM-DD HH24:MI:SS') , 'DAY') AS day_explicit
;
根据 Oracle 文档“如果省略 fmt,则日期将四舍五入到最近的一天”,“DAY”参数仅表示 DAY。
ROUND(date_value, 'DAY')
正在四舍五入到最近的一周开始时间。
ROUND(date_value, 'DD')
四舍五入到最近的一天。
这记录在ROUND 和 TRUNC 日期函数文档中:
格式化模型 舍入或截断单位 DDD
DD
J日 白天
DY
D一周的开始日
例如:
如果您有样本数据:
CREATE TABLE table_name (dt) AS
SELECT TRUNC(DATE '2024-06-26', 'IW') + LEVEL - 1 + INTERVAL '15:02:18' HOUR TO SECOND
FROM DUAL
CONNECT BY LEVEL <= 7;
你使用:
ALTER SESSION SET NLS_TERRITORY = 'Germany'
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS (DY)';
SELECT dt,
ROUND(dt) AS default_result,
ROUND(dt, 'DAY') AS day_explicit,
ROUND(dt, 'DD') AS dd_explicit
FROM table_name;
那么输出是:
DT | 默认结果 | DAY_EXPLICIT | DD_EXPLICIT |
---|---|---|---|
2024-06-24 15:02:18(周一) | 2024-06-25 00:00:00(星期二) | 2024-06-24 00:00:00(周一) | 2024-06-25 00:00:00(星期二) |
2024-06-25 15:02:18(星期二) | 2024-06-26 00:00:00(周三) | 2024-06-24 00:00:00(周一) | 2024-06-26 00:00:00(周三) |
2024-06-26 15:02:18(周三) | 2024-06-27 00:00:00 (周四) | 2024-06-24 00:00:00(周一) | 2024-06-27 00:00:00 (周四) |
2024-06-27 15:02:18(周四) | 2024-06-28 00:00:00(周五) | 2024-07-01 00:00:00(周一) | 2024-06-28 00:00:00(周五) |
2024-06-28 15:02:18(周五) | 2024-06-29 00:00:00 (周六) | 2024-07-01 00:00:00(周一) | 2024-06-29 00:00:00 (周六) |
2024-06-29 15:02:18(周六) | 2024-06-30 00:00:00(周日) | 2024-07-01 00:00:00(周一) | 2024-06-30 00:00:00(周日) |
2024-06-30 15:02:18(周日) | 2024-07-01 00:00:00(周一) | 2024-07-01 00:00:00(周一) | 2024-07-01 00:00:00(周一) |
由于在欧洲大部分地区,一周的开始是星期一。
如果你这样做:
ALTER SESSION SET NLS_TERRITORY = 'America'
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS (DY)';
SELECT dt,
ROUND(dt) AS default_result,
ROUND(dt, 'DAY') AS day_explicit,
ROUND(dt, 'DD') AS dd_explicit
FROM table_name;
那么输出是:
DT | 默认结果 | DAY_EXPLICIT | DD_EXPLICIT |
---|---|---|---|
2024-06-24 15:02:18(周一) | 2024-06-25 00:00:00(星期二) | 2024-06-23 00:00:00(周日) | 2024-06-25 00:00:00(星期二) |
2024-06-25 15:02:18(星期二) | 2024-06-26 00:00:00(周三) | 2024-06-23 00:00:00(周日) | 2024-06-26 00:00:00(周三) |
2024-06-26 15:02:18(周三) | 2024-06-27 00:00:00 (周四) | 2024-06-30 00:00:00(周日) | 2024-06-27 00:00:00 (周四) |
2024-06-27 15:02:18(周四) | 2024-06-28 00:00:00(周五) | 2024-06-30 00:00:00(周日) | 2024-06-28 00:00:00(周五) |
2024-06-28 15:02:18(周五) | 2024-06-29 00:00:00 (周六) | 2024-06-30 00:00:00(周日) | 2024-06-29 00:00:00 (周六) |
2024-06-29 15:02:18(周六) | 2024-06-30 00:00:00(周日) | 2024-06-30 00:00:00(周日) | 2024-06-30 00:00:00(周日) |
2024-06-30 15:02:18(周日) | 2024-07-01 00:00:00(周一) | 2024-06-30 00:00:00(周日) | 2024-07-01 00:00:00(周一) |
Oracle 认为美国一周的开始是周日。
如果你这样做:
ALTER SESSION SET NLS_TERRITORY = 'Bangladesh'
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS (DY)';
SELECT dt,
ROUND(dt) AS default_result,
ROUND(dt, 'DAY') AS day_explicit,
ROUND(dt, 'DD') AS dd_explicit
FROM table_name;
那么输出是:
DT | 默认结果 | DAY_EXPLICIT | DD_EXPLICIT |
---|---|---|---|
2024-06-24 15:02:18(周一) | 2024-06-25 00:00:00(星期二) | 2024-06-28 00:00:00(周五) | 2024-06-25 00:00:00(星期二) |
2024-06-25 15:02:18(星期二) | 2024-06-26 00:00:00(周三) | 2024-06-28 00:00:00(周五) | 2024-06-26 00:00:00(周三) |
2024-06-26 15:02:18(周三) | 2024-06-27 00:00:00 (周四) | 2024-06-28 00:00:00(周五) | 2024-06-27 00:00:00 (周四) |
2024-06-27 15:02:18(周四) | 2024-06-28 00:00:00(周五) | 2024-06-28 00:00:00(周五) | 2024-06-28 00:00:00(周五) |
2024-06-28 15:02:18(周五) | 2024-06-29 00:00:00 (周六) | 2024-06-28 00:00:00(周五) | 2024-06-29 00:00:00 (周六) |
2024-06-29 15:02:18(周六) | 2024-06-30 00:00:00(周日) | 2024-06-28 00:00:00(周五) | 2024-06-30 00:00:00(周日) |
2024-06-30 15:02:18(周日) | 2024-07-01 00:00:00(周一) | 2024-06-28 00:00:00(周五) | 2024-07-01 00:00:00(� 75e1 �一) |
孟加拉国周五是一周的开始。
注意:如果您希望始终四舍五入到星期一,请使用
IW
格式模型作为 ISO 周的开始(由 ISO 8601 定义)。