Oracle 23c ROUND 与 DATE 数据类型

问题描述 投票:0回答:1

我遇到了 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。

结果看起来像这样 -> day_explicit 列不应该像 2024-06-27 吗?

sql oracle date rounding
1个回答
2
投票

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;

那么输出是:

"\n"
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 定义)。

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.