首页 > 解决方案 > Oracle -- 根据 varchar 时间戳提取月度数据

问题描述

我有一个 oracle 数据库,我试图按月从中提取数据。

我正在查询的表和字段具有以下结构

select ID, lastmodifieddate as LMDate from salesforce.X_TASK WHERE ROWNUM <= 10
('ID', <cx_Oracle.DbType DB_TYPE_VARCHAR>, 18, 18, None, None, 1)
('LMDATE', <cx_Oracle.DbType DB_TYPE_VARCHAR>, 25, 25, None, None, 1)
('00T4N00002QhFvjUAF', '2019-09-06T21:05:04.000Z')
('00T4N00002QhFvmUAF', '2019-09-06T21:05:04.000Z')
('00T4N00002QhFvnUAF', '2019-09-06T21:05:04.000Z')
('00T4N00002QhFvsUAF', '2019-09-06T21:05:04.000Z')
('00T4N00002QhFvtUAF', '2019-09-06T21:05:04.000Z')
('00T4N00002QhFw0UAF', '2019-09-06T21:05:04.000Z')
('00T4N00002QhFw1UAF', '2019-09-06T21:05:04.000Z')
('00T4N00002QhFwAUAV', '2019-09-06T21:05:09.000Z')
('00T4N00002QhFwBUAV', '2019-09-06T21:05:09.000Z')
('00T4N00002QhFwMUAV', '2019-09-06T21:05:09.000Z')

仅从 varchar 时间戳字段中提取日期的最佳方法是什么?

我尝试将字段更改为_char

select ID, to_char(LASTMODIFIEDDATE, 'YYYY-MM-DD') from salesforce.X_TASK 
WHERE LASTMODIFIEDDATE >= to_date('2020-05-31', 'YYYY-MM-DD') 
and  LASTMODIFIEDDATE < to_date('2020-06-30', 'YYYY-MM-DD')

但最终出现此错误

ORA-01861: literal does not match format string

如果我尝试将其更改为日期,则相同

select ID, to_date(LASTMODIFIEDDATE, 'YYYY-MM-DD') from salesforce.X_TASK 
WHERE LASTMODIFIEDDATE >= to_date('2020-05-31', 'YYYY-MM-DD') 
and  LASTMODIFIEDDATE < to_date('2020-06-30', 'YYYY-MM-DD')

ORA-01861: literal does not match format string

标签: sqloracle

解决方案


究竟什么是“时间戳”?它看起来怎样?日期、时间最多...秒?

无论如何:因为您将时间戳存储为字符串(通常是坏主意),并且如果它的所有值共享相同的格式(例如25.02.2021 20:02:00,它是dd.mm.yyyy hh24:mi:ss),那么最简单的方法是使用SUBSTR函数。在你的情况下:

select id,
       substr(lastmodifieddate, 1, 10) as datum
from salesforce.X_TASK 
where to_date(lastmodifieddate, 'dd.mm.yyyy') >= to_date('2020-05-31', 'YYYY-MM-DD') 
  and to_date(lastmodifieddate, 'dd.mm.yyyy') <  to_date('2020-06-30', 'YYYY-MM-DD');

当然,如果格式不是dd.mm.yyyy(如我的示例),您将使用您的。请注意,如果存在不遵循这种格式的值,包含字母等,查询将失败。这就是为什么我说将时间戳(或日期)存储为字符串是一个坏主意。


阅读您的评论后:似乎该列包含大量数据,而不仅仅是时间戳。好的然后 - 从中​​提取日期片段。SUBSTR + INSTR会做:

SQL> with test (col) as
  2    (select q'[<cx_Oracle.DbType DB_TYPE_VARCHAR>, 25, 25, None, None, 1) ('2016-10-27T19:27:14.000Z')]'
  3     from dual
  4    )
  5  select substr(col, instr(col, '(') + 2, 10) datum
  6  from test
  7  /

DATUM
----------
2016-10-27

SQL>

现在,TO_DATE使用适当的格式掩码对其应用并在WHERE子句中使用它:

select id,
       to_date(substr(lastmodifieddate, instr(lastmodifieddate, '(') + 2, 10), 'yyyy-mm-dd') datum
from x_task
where to_date(substr(lastmodifieddate, instr(lastmodifieddate, '(') + 2, 10), 'yyyy-mm-dd') >= to_date('2020-05-31', 'YYYY-MM-DD') 
  and to_date(substr(lastmodifieddate, instr(lastmodifieddate, '(') + 2, 10), 'yyyy-mm-dd') <  to_date('2020-06-30', 'YYYY-MM-DD');

推荐阅读