SQL - 如何打印计算的日期时间结果

SQL - How to print calculated datetime result

[user@hostname ~]$ sqlplus -v
SQL*Plus: Release 19.0.0.0.0 - Production
Version 19.3.0.0.0
select
a.user_id as user_id, 
/* convert to minutes */
(to_date(a.modified_datetime, 'yyyy/mm/dd hh24:mi:ss') - to_date(b.modified_datetime, 'yyyy/mm/dd hh24:mi:ss')) 60 * 24 as minutes
from 
(select user_id, modified_datetime, from table_name where some_conditions) a,
(select user_id, modified_datetime, from table_name where other_conditions) b,
where a.user_id = b.user_id
;

如果 a.modified_datetime'2021/10/01 13:00:00' 并且 b.modified_datetime'2021/10/01 12:30:00',则此查询的结果将是:

user_id minutes
------- -------
  12345      30

然而,我运行这个查询通过sqlplus,它returns

user_id minutes
------- -------
  12345       0

这个查询有什么问题,或者需要为 sqlplus 设置一些选项?

30 分钟,如果值确实如您所述:

SQL> with test (a_time, b_time) as
  2    (select to_date('2021/10/01 13:00:00', 'yyyy/mm/dd hh24:mi:ss'),
  3            to_date('2021/10/01 12:30:00', 'yyyy/mm/dd hh24:mi:ss')
  4     from dual
  5    )
  6  select (a_time - b_time) * 60 * 24 as minutes
  7  from test;

   MINUTES
----------
        30

SQL>

it is stored in a date column

正如@a_horse_with_no_name 在评论中指出的那样,在已经是日期的值上调用 to_date() 是不正确的,并且会导致您明显的问题。

当你这样做时:

to_date(a.modified_datetime, 'yyyy/mm/dd hh24:mi:ss')

您正在使用当前会话 NLS 设置将日期隐式转换为字符串;以仍然默认的 DD-MON-RR 为例,这确实是在做:

to_date(a.modified_datetime, 'yyyy/mm/dd hh24:mi:ss')
-> to_date(to_char(a.modified_datetime), 'yyyy/mm/dd hh24:mi:ss')
-> to_date(to_char(a.modified_datetime, <NLS_DATE_FORMAT>), 'yyyy/mm/dd hh24:mi:ss')
-> to_date(to_char(a.modified_datetime, 'DD-MON-RR'), 'yyyy/mm/dd hh24:mi:ss')
-> to_date('01-OCT-21', 'yyyy/mm/dd hh24:mi:ss')
-> 0001-10-21 00:00:00

由于两个值都以午夜结束,因此它们之间的差异计算为零分钟。

可以更改 NLS 设置,这很脆弱;或将日期显式转换为正确格式的字符串 - 但既没有必要也没有用。

您根本不应该进行 to_date() 调用,可以直接将日期值彼此相减:

select
a.user_id as user_id,
(a.modified_datetime - b.modified_datetime) * 60 * 24 as minutes
from 
(select user_id, modified_datetime from table_name where some_conditions) a,
(select user_id, modified_datetime from table_name where other_conditions) b
where a.user_id = b.user_id;

或使用 ANSI 连接:

select
a.user_id as user_id,
(a.modified_datetime - b.modified_datetime) * 60 * 24 as minutes
from 
(select user_id, modified_datetime from table_name where some_conditions) a
join
(select user_id, modified_datetime from table_name where other_conditions) b
on a.user_id = b.user_id;

db<>fiddle 显示隐式转换的结果和正确的输出。