【问题标题】:Oracle query, get count of records by hourOracle查询,按小时获取记录数
【发布时间】:2021-10-05 19:01:36
【问题描述】:

我正在尝试获取每小时的交易计数。通常这是一个直接的查询,不幸的是,我必须使用的时间戳列不是时间戳,而是 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');

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

【问题讨论】:

  • 如果您匹配了 some 示例数据,您在该 VARCHAR2 列中,则只有 some 值将被识别为“有效”。其余的(您没有看到的,不知道它们存在的,...)不会,Oracle 将针对这些值引发错误。这就是将日期存储为字符串时发生的情况,因为数据库本身不会阻止用户将日期输入为“LI/TT/LEFO OT”,因此 - 一旦您对其应用 MM/DD/YYYY HH24 格式掩码,您将得到一个错误。因此,永远不要将日期存储为字符串。
  • 您是否尝试过使用TO_TIMESTAMP 函数(Oracle Documentation)将您的VARCHAR2 转换为时间戳?
  • 就@Littlefoot 而言,如果您仍然收到错误,您可能需要在 where 子句中添加 REGEXP_LIKE 以确保仅返回有效条目。
  • @Littlefoot 我继承了这个数据库和它的设计,所以我现在必须忍受它。
  • @Del 我已经尝试了在阳光下进行的一切转换,但没有任何工作,很可能是因为 Littlefoor 所说的。有没有办法找到不合格的条目?

标签: sql oracle12c date-format


【解决方案1】:

假设您的列始终采用 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小提琴here

【讨论】:

    【解决方案2】:

    假设正如 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 函数。然后它会捕获任何错误并返回NULL。这可以避免您的不良数据弄乱您的查询。之后,查询与您之前尝试的差不多。我在内部查询中将时间戳截断为小时,然后在外部查询中使用它来分组(仅使用没有 NULL 时间戳的行...意味着它们没有错误)

    【讨论】:

      猜你喜欢
      • 2022-12-05
      • 2019-03-18
      • 2012-04-22
      • 1970-01-01
      • 1970-01-01
      • 2014-03-17
      • 1970-01-01
      • 2019-12-03
      • 1970-01-01
      相关资源
      最近更新 更多