Oracle查询,按小时获取记录数

Oracle query, get count of records by hour

我正在尝试获取每小时的交易计数。通常这是一个直接的查询,不幸的是我必须使用的时间戳列不是时间戳而是 varchar2!无论我尝试什么,我都会得到“无效月份”或“无效数字”,具体取决于我使用的格式。

时间戳看起来像:2021-08-08 00:00:52:632

我还执行了以下命令来获取 NLS 格式:

SELECT * FROM nls_session_parameters WHERE parameter = 'NLS_DATE_FORMAT';

并获得

DD-MON-RRRR.

这是我在其他十几个中尝试过的最新一个(我注释掉了“group by”只是为了显示该死的东西)。

select to_char(reqts,'mm/dd/yyyy hh24') DATE_HR
--, count(*)
from idcreqresplog
where logdate > trunc(SYSDATE -2)
and logtypeid in (2,4)
--group by to_char(reqts,'mm/dd/yyyy hh24');

还有

select to_char(reqts, 'yyyy-mm-dd hh24:mi:ss.fff' )
--, count(*) 
FROM 
reqresplog 
WHERE 
logdate > trunc(SYSDATE -2) ;
--group by to_date(reqts, 'yyyy-mm-dd HH4');

我束手无策,需要一些帮助。

假设如 LittleFoot 所建议的那样,您的某些数据是错误的,您可以使用内联 WITH 函数来根除错误数据。举个例子:

WITH FUNCTION get_timestamp
(
  p_sTimeString VARCHAR2
)
RETURN TIMESTAMP
IS
BEGIN
  RETURN TO_TIMESTAMP(p_sTimeString, 'YYYY-MM-DD HH24:MI:SS.FF3');
EXCEPTION WHEN OTHERS THEN RETURN NULL;
END;
SELECT TO_CHAR(s.hour, 'YYYY-MM-DD HH24') AS HOUR, COUNT(*) AS ROW_COUNT
FROM (SELECT TRUNC(get_timestamp(td.time), 'HH24') AS HOUR,
             td.amount
      FROM test_data td) s
WHERE s.hour IS NOT NULL
GROUP BY s.hour
ORDER BY s.hour;

这里是 DBFiddle,显示了它对一些好数据和坏数据的工作情况 (Link)。

查询所做的是使用内联函数调用 TO_TIMESTAMP 函数。然后它只捕获任何错误和 returns NULL。这可以避免您的不良数据弄乱您的查询。之后,查询与您之前尝试的几乎一样。我在内部查询中将时间戳截断为小时,然后在外部查询中使用它进行分组(仅使用没有 NULL 时间戳的行......这意味着它们没有错误)

假设您的列始终采用 2021-08-08 00:00:52:63 格式,然后将子字符串分组到第 13 个字符:

SELECT SUBSTR(reqts, 1, 13) AS date_hr,
       count(*)
FROM   idcreqresplog
WHERE  logdate > trunc(SYSDATE -2)
AND    logtypeid in (2,4)
GROUP BY
       SUBSTR(reqts, 1, 13);

如果您确实想转换为日期,那么从 Oracle 12.2 开始,您可以使用 TO_TIMESTAMP(string_value DEFAULT NULL ON CONVERSION ERROR, 'YYYY-MM-DD HH24:MI:SS:FF'):

SELECT TRUNC(
         TO_TIMESTAMP(
           reqts DEFAULT NULL ON CONVERSION ERROR,
           'YYYY-MM-DD HH24:MI:SS:FF'
         ),
         'HH'
       ) AS date_hr,
       COUNT(*)
FROM   idcreqresplog
WHERE  logdate > trunc(SYSDATE -2)
AND    logtypeid in (2,4)
GROUP BY
       TRUNC(
         TO_TIMESTAMP(
           reqts DEFAULT NULL ON CONVERSION ERROR,
           'YYYY-MM-DD HH24:MI:SS:FF'
         ),
         'HH'
       )

db<>fiddle here