简体   繁体   中英

Oracle — Pulling monthly data based on varchar timestamp

I have an oracle database that I'm trying to extract data from on a month by month basis.

The table and field I'm querying has the following structure

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')

What is the best way to extract only the date from the varchar timestamp field?

I have tried changing the field to_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')

But end up with this error

ORA-01861: literal does not match format string

Same if I try to change it to a date

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

What do you call a "timestamp", exactly? How does it look like? Date, time up to... seconds?

Anyway: as you're storing timestamp as a string (bad idea, generally), and if all of its values share the same format (eg 25.02.2021 20:02:00 which is dd.mm.yyyy hh24:mi:ss ), then the simplest way to do that is to use a SUBSTR function. In your case:

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');

Of course , if format isn't dd.mm.yyyy (as in my example), you'd use yours. Note that query will fail if there are value that don't follow such a format, contain letters, whatnot. That's why I said that storing timestamps (or dates) as strings is a bad, BAD idea.


After reading your comment: it seems that column contains whole lot of data, not only the timestamp. OK then - extract the date piece out of it. SUBSTR + INSTR would do:

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>

Now, apply TO_DATE to it with appropriate format mask and use it in WHERE clause:

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');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM