drk*_*drk 2 sql oracle date rounding
我遇到过 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
;
Run Code Online (Sandbox Code Playgroud)
根据 Oracle文档“如果省略 fmt,则日期将四舍五入到最近的一天”,“DAY”参数仅表示“DAY”。
MT0*_*MT0 10
ROUND(date_value, 'DAY')舍入到最近的一周开始时间(由会话/数据库参数定义NLS_TERRITORY)。
ROUND(date_value, 'DD')四舍五入到最近的一天。
这记录在ROUND 和 TRUNC 日期函数文档中:
格式模型 舍入或截断单位 DDDDJ
天 DAY
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;
Run Code Online (Sandbox Code Playgroud)
你使用:
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;
Run Code Online (Sandbox Code Playgroud)
那么输出是:
| 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;
Run Code Online (Sandbox Code Playgroud)
那么输出是:
| 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;
Run Code Online (Sandbox Code Playgroud)
那么输出是:
| 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(周一) |
在孟加拉国,周五是一周的开始。
同样,如果您将 设为NLS_TERRITORY中东国家,那么您通常会发现一周从星期六开始。
注意:如果您希望始终四舍五入到星期一,请使用IWISO 周开始的格式模型(由 ISO 8601 定义)。