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 显示隐式转换的结果和正确的输出。
[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 显示隐式转换的结果和正确的输出。