我有一个Oracle查询,奇怪的是查询结果有时是不同的。
select
cast(pmm_datetime - 1 / 24 * utc_offset as timestamp) as pmm_datetime_utc,
count(distinct(NODEB_NAME)) as num_of_recs
from pmmcounter_db.WC_B_NODEBFUNCTION_QH t1
where pmm_datetime >= to_timestamp('201810230525','YYYYMMDDHH24MI')
and cast(pmm_datetime - 1 / 24 * utc_offset as timestamp) = '2018-10-22 19:15:00.000'
group by cast(pmm_datetime - 1 / 24 * utc_offset as timestamp)
大多数情况下,查询返回的预期结果如下:
PMM_DATETIME_UTC NUM_OF_RECS
2018-10-22 19:15:00.000 6930
但是,它随机返回了如下结果。如您所见,相同的日期时间和状态分为几行。
PMM_DATETIME_UTC NUM_OF_RECS
2018-10-22 19:15:00.000 785
2018-10-22 19:15:00.000 1990
2018-10-22 19:15:00.000 162
2018-10-22 19:15:00.000 3993
更奇怪的是,我尝试通过对QH_NUM_OF_RECS使用sum来放置另一个组,结果是相同的。看来Oracle无法按PMM_DATETIME_UTC分组?
这是怎么回事?为什么查询结果可能会不同???????
答案 0 :(得分:2)
不要从TIMESTAMP
数据类型中减去数字;这是Oracle对DATE
数据类型应用的一种操作,会将TIMESTAMP
隐式转换为DATE
并失去精度(然后您必须应用显式转换将其转换回)。
相反,减去INTERVAL
的倍数(或使用NUMTODSINTERVAL( utc_offset, 'HOUR' )
生成间隔):
SELECT pmm_datetime - utc_offset * INTERVAL '1' HOUR as pmm_datetime_utc,
COUNT( DISTINCT NODEB_NAME ) as num_of_recs
FROM pmmcounter_db.WC_B_NODEBFUNCTION_QH t1
WHERE pmm_datetime >= TIMESTAMP '2018-10-23 05:25:00'
AND pmm_datetime - utc_offset * INTERVAL '1' HOUR = TIMESTAMP '2018-10-22 19:15:00.000'
GROUP BY pmm_datetime - utc_offset * INTERVAL '1' HOUR
您还可以使用时间戳文字TIMESTAMP '2018-10-22 19:15:00.000'
,而不是依赖从字符串到TIMESTAMP
数据类型的隐式转换。
您还可以使用TIMESTAMP WITH TIME ZONE
数据类型通过FROM_TZ
函数和AT TIME ZONE 'UTC'
管理到UTC的转换。
为什么查询结果会不同?
TIMESTAMP(6)
数据类型可以包含微秒值。如果您只对微秒值感兴趣,则将该值转换为TIMESTAMP(3)
以降低精度。
您可以使用:
SELECT TO_CHAR(
pmm_datetime - utc_offset * INTERVAL '1' HOUR,
'YYYY-MM-DD HH24:MI:SS.FF6'
) as pmm_datetime_utc,
COUNT( DISTINCT NODEB_NAME ) as num_of_recs
...
看看是否是这种情况。
答案 1 :(得分:1)
尝试使用以下代码。它可以解决问题。您在选择,其中和分组依据中重复了cast(pmm_datetime - 1 / 24 * utc_offset as timestamp)
表达式,这些表达式可能返回不同的值。在代码中重复行的原因是group by
。
with
cte
as
(
select
cast(pmm_datetime - 1 / 24 * utc_offset as timestamp) as pmm_datetime_utc,
NODEB_NAME as num_of_recs
from
pmmcounter_db.WC_B_NODEBFUNCTION_QH t1
where
pmm_datetime >= to_timestamp('201810230525','YYYYMMDDHH24MI')
)
select
pmm_datetime_utc,
count(distinct(NODEB_NAME)) as num_of_recs
from
cte
where
pmm_datetime_utc = '2018-10-22 19:15:00.000'
group by
pmm_datetime_utc;