【问题标题】:What is the reason to use trunc(date)使用 trunc(date) 的原因是什么
【发布时间】:2021-10-27 07:51:01
【问题描述】:

trunc 有什么用?例如,我想根据这个 12-Mar-1996 显示人的年龄

select bo.journeystatus As "Journey Status",bo.bookingdate As "Booking Date",bo.fromdestination As "Location From",bo.todestination As "Desired Location", co.customerid As "Customer ID", co.customername As "Customer Name", co.customertel AS "Customer Phone No"
     , concat(TRUNC((SYSDATE - TO_DATE(co.customerdob, 'DD-MON-YYYY'))/ 365.25),' years old') as "Customer Age", co.customergender as "Gender"
from   booking bo, customer co
where  bo.journeystatus = 'Pending' and bo.bookingdate between to_date('01-'||in_month||'-'||in_year,'dd-mm-yyyy') AND to_date('30-'||in_month||'-'||in_year,'dd-mm-yyyy') and bo.customerid = co.customerid
group by bo.journeystatus, bo.fromdestination,bo.todestination, bo.bookingdate, co.customerid, co.customername, co.customertel, co.customerdob, co.customergender
order by bookingdate;

上面的说法是正确的,我只是不明白为什么需要它?我去网上看了那些文章,还是看不懂?谁能用更简单的方式向我解释一下?

为什么需要trunc(date)

concat(TRUNC((SYSDATE - TO_DATE(co.customerdob, 'DD-MON-YYYY'))/ 365.25),' years old')

【问题讨论】:

  • 在 Oracle trunc(date) 中删除时间元素。仅返回日期(午夜)。数据类型 DATE 始终存储日期 + 时间。
  • 我明白了,但是,如果 sysdate - todate(),值如何返回 (25),我是否指定只扣除年份?
  • "TRUNC 删除数字的小数部分。INT 根据数字小数部分的值将数字向下舍入到最接近的整数。" Round vs. Trunc。只需删除您的 TRUNC() 函数,您就可以看到不同之处:)
  • 请注意,您的示例不是trunc(date),而是trunc(number),因为sysdate - someotherdate 给出了天数的差异。此外,co.customerdob 需要转换为日期似乎很奇怪。通常,您会将其存储为日期,并且不需要任何转换。

标签: sql oracle date truncate


【解决方案1】:

让我们通过例子来学习:

SELECT (SYSDATE - TO_DATE('30-03-1996', 'DD-MM-YYYY')) age
FROM DUAL;

-- Output - Total days (9281) and time (0.55410...) since 30-03-1996.
-- 
-- 9281.554108796296296296296296296296296296
--

SELECT (SYSDATE - TO_DATE('30-03-1996', 'DD-MM-YYYY')/ 365.25 age
FROM DUAL;

-- Output - Total years (25) and months/days/hours... (0.411519...) since 30-03-1996.
-- 
-- 25.41151953887494613025071615078459705428
--

-- Use trunc to cut off the decimal part
SELECT TRUNC((SYSDATE - TO_DATE('30-03-1996', 'DD-MM-YYYY'))/365.25) age
FROM DUAL;

-- Output - Total years (25) since 30-03-1996.
-- 
-- 25
--


【讨论】:

  • 天啊!非常感谢你解释gg!我现在真的明白了!
  • 为了得到一个人的年龄,我宁愿用months_between
  • 会记住这一点,感谢您的建议!赞赏!
【解决方案2】:

啊!一堆乱七八糟的无格式运行代码。我必须通过自动格式化程序运行它才能阅读并理解它。这本身并不能回答你的问题,但我不能让它在没有评论的情况下通过,而且这个平台的限制不允许在“评论”中进行解释。

SELECT bo.journeystatus   AS "Journey Status",
       bo.bookingdate     AS "Booking Date",
       bo.fromdestination AS "Location From",
       bo.todestination   AS "Desired Location",
       co.customerid      AS "Customer ID",
       co.customername    AS "Customer Name",
       co.customertel     AS "Customer Phone No",
       Concat(Trunc(( SYSDATE - To_date(co.customerdob, 'DD-MON-YYYY') ) /
                    365.25),
       ' years old')      AS "Customer Age",
       co.customergender  AS "Gender"
FROM   booking bo,
       customer co
WHERE  bo.journeystatus = 'Pending'
       AND bo.bookingdate BETWEEN To_date('01-'
                                          ||in_month
                                          ||'-'
                                          ||in_year, 'dd-mm-yyyy') AND
                                      To_date('30-'
                                              ||in_month
                                              ||'-'
                                              ||in_year, 'dd-mm-yyyy')
       AND bo.customerid = co.customerid
GROUP  BY bo.journeystatus,
          bo.fromdestination,
          bo.todestination,
          bo.bookingdate,
          co.customerid,
          co.customername,
          co.customertel,
          co.customerdob,
          co.customergender
ORDER  BY bookingdate;  

这让我大吃一惊:

Concat(Trunc(( SYSDATE - To_date(co.customerdob, 'DD-MON-YYYY') ) /

函数 TO_DATE 将字符串作为其输入。这意味着两个条件之一为真:

  1. co.customerdob 列是 to_date 所期望的字符串数据类型(VARCHAR 或 VARCHAR2)。如果是这种情况,则说明您存在严重的设计缺陷。日期/时间应该是两种可能的日期时间类型之一 - DATE 或 TIMESTAMP。存储为 DATE 或 TIMESTAMP 可以强制执行完整性并允许简单的日期/时间算术。存储为 VARCHAR 都不允许。

  1. co.customerdob 列应该是一个 DATE。如果是这种情况,您的代码就有缺陷,因为将有一个隐式 TO_CHAR 函数来将 co.customerdob 放入 TO_DATE 所期望的字符串中。而这个隐含的 to_char 将取决于 NLS_DATE_FORMAT 的默认或会话设置,这可能是也可能不是您所期望和依赖的。

【讨论】:

  • 解决2.语句,只要加上这条SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'DD/MON/YYYY';,就可以解决了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-10
  • 1970-01-01
  • 1970-01-01
  • 2021-08-31
  • 2015-10-28
  • 2015-12-09
  • 1970-01-01
相关资源
最近更新 更多