我有一个名为trans_info的表。
| 日期_d|重量|
| --------------|--------------|
| 2016年1月1日|三|
| 2016-01-02 2016-01-02|二|
| 2016-01-03 2016-01-03|1|
| 2016-01-05 2016-01-05|四|
当我执行SQL时
with m1 as (
select
ti.date_d,ti.weight,row_number() over(order by ti.date_d) rn
from trans_info ti
),m2(date_d,weight,rn,start_date) as (
select
date_d,weight,rn,date_d as start_date
from m1 where rn=1
union all
select
a.date_d,a.weight,a.rn,
case when b.start_date+4 <= a.date_d then a.date_d else b.start_date end
from m1 a,m2 b where b.rn+1=a.rn
)
select * from m2
结果是
| 日期_d|重量|开始日期|
| --------------|--------------|--------------|
| 2016年1月1日|三|2016年1月1日|
| 2016-01-02 2016-01-02|二|2016-01-02 2016-01-02|
| 2016-01-03 2016-01-03|1|2016-01-03 2016-01-03|
| 2016-01-05 2016-01-05|四|2016-01-05 2016-01-05|
但是,当我将sql更改为以下内容时
with m1 as (
select
ti.date_d,ti.weight,row_number() over(order by ti.date_d) rn
from trans_info ti
),m2(date_d,weight,rn,start_date) as (
select
date_d,weight,rn,date_d as start_date
from m1 where rn=1
union all
select
a.date_d,a.weight,a.rn,
case when 4 <= a.date_d-b.start_date then a.date_d else b.start_date end
from m1 a,m2 b where b.rn+1=a.rn
)
select * from m2
结果是
| 日期_d|重量|开始日期|
| --------------|--------------|--------------|
| 2016年1月1日|三|2016年1月1日|
| 2016-01-02 2016-01-02|二|2016年1月1日|
| 2016-01-03 2016-01-03|1|2016年1月1日|
| 2016-01-05 2016-01-05|四|2016-01-05 2016-01-05|
两个sql之间的唯一区别是日期的比较。
b.start_date+4 <= a.date_d
4 <= a.date_d-b.start_date
这真的很奇怪。为什么?。我在Oracle 11 g上执行SQL。
2条答案
按热度按时间zdwk9cvp1#
在Oracle中,
DATE
是一种二进制数据类型,由7个字节组成,代表世纪,世纪年,月,日,小时,分钟和秒。它始终具有这7个组件,并且从不以任何特定的人类可读格式存储。客户端应用程序(例如SQL Developer、SQL*Plus等)通常选择不以原始二进制形式显示
DATE
,而是以人类可读的字符串显示。这并不意味着这些组件不存在,只是它们没有显示给您。要显示整个值,可以用途:
或者,在SQL Developer或SQL*Plus中,您可以使用以下命令更改日期的默认显示格式:
至于你的数据,如果你的日期有午夜时间成分,那么两个查询输出完全相同的值。
如果你的日期有非午夜时间组件,那么你会得到不同的行为,正如你所看到的。
然后两个查询输出:
| 日期|重量|注册护士|开始日期|
| --------------|--------------|--------------|--------------|
| 2016年01月01日上午00时00分|三|1|2016年01月01日上午00时00分|
| 2016年01月02日上午00时00分|二|二|2016年01月01日上午00时00分|
| 2016-01-03 00:00:00|1|三|2016年01月01日上午00时00分|
| 2016年01月05日上午00时00分|四|四|2016-01-05 00:00:00|
如果您这样做:
然后输出更改为:
| 日期|重量|注册护士|开始日期|
| --------------|--------------|--------------|--------------|
| 2016-01-01 23:59:59|三|1|2016-01-01 23:59:59|
| 2016年01月02日上午00时00分|二|二|2016-01-01 23:59:59|
| 2016-01-03 00:00:00|1|三|2016-01-01 23:59:59|
| 2016-01-05 00:00:00|四|四|2016-01-01 23:59:59|
如果将查询更改为:
然后恢复原始行为:
| 日期|重量|注册护士|开始日期|
| --------------|--------------|--------------|--------------|
| 2016年01月01日上午00时00分|三|1|2016年01月01日上午00时00分|
| 2016年01月02日上午00时00分|二|二|2016年01月01日上午00时00分|
| 2016-01-03 00:00:00|1|三|2016年01月01日上午00时00分|
| 2016-01-05 00:00:00|四|四|2016-01-05 00:00:00|
fiddle
xkrw2x1b2#
我在Oracle 11 g上执行SQL
递归子查询分解是11 g发行版2中的新功能,有很多bug。它可能是11840579,因为这是专门关于日期的,但也可能是其他东西,或者是一个未发布的错误。
正如@MTO的fiddle所示,在21 c中,查询得到的结果相同,但是in an unpatched 11.2.0.1 fiddle,前两个查询得到的结果与您所做的完全相同。(还要注意,第四个查询得到一个错误,这似乎是基础版本中的另一个错误)。
假设你还在使用基础版本,如果你有支持合同,你可能仍然可以修补到11.2.0.4,或者升级到更新的版本,在那里这个问题得到了解决。
否则,您只需要仔细检查结果并修改查询以解决遇到的任何异常情况。