Oracle :Compare dates only by the Hour - sql

We have a table which has a DATE column d.
I'd like to get all the rows where the d column is greater / lower than some value, regardless of the date.
For example
| d |
-------------------
|2009/11/1 15:55:23|
--------------------
|2009/11/2 15:55:23|
--------------------
|2009/11/3 15:55:23|
--------------------
|2009/11/3 17:55:23|
--------------------
For example, If I want all the records marked after 5 PM:
select d
from my_table
where extract( hour from d ) > TO_DATE ('17:00:00','HH24:MI:SS')
This should return only one record
|2009/11/3 17:55:23|
I don't know if this is the best way to do it, but I get an error on the extract function:
ORA-30076: invalid extract field for extract source
Cause: The extract source does not contain the specified extract field.
Is there a better way to do this?
Whats up with that error? extract only available for sysdate, as in all examples i've found?
Thanks in advance

How about this?
select d
from my_table
where to_char(d,'HH24') > '16';

Don't have an Oracle database to test with at the moment but I think the following should work:
SELECT *
FROM MY_TABLE t
WHERE EXTRACT(HOUR FROM CAST(t.D AS TIMESTAMP)) > 16;
But I don't understand why the CAST would be needed as this page says that HOUR is a valid field in a DATE.
Share and enjoy.

Try this:
select d from my_table
where (d-trunc(d)) > 16/24;

Related

query to subtract date from systimestamp in oracle 11g

I want to perform a subtraction operation on the date returned from another query and the system time in oracle SQL. So far I have been able to use the result of another query but when I try to subtract from systimestamp it gives me the following error
ORA-01722: invalid number
'01722. 00000 - "invalid number"
*Cause: The specified number was invalid.
*Action: Specify a valid number.
Below is my query
select round(to_number(systimestamp - e.last_time) * 24) as lag
from (
select ATTR_VALUE as last_time
from CONFIG
where ATTR_NAME='last_time'
and PROCESS_TYPE='new'
) e;
I have also tried this
select to_char(sys_extract_utc(systimestamp)-e.last_time,'YYYY-MM-DD HH24:MI:SS') as lag
from (
select ATTR_VALUE as last_time
from CONFIG
where ATTR_NAME='last_time'
and PROCESS_TYPE='new'
) e;
I want the difference between the time intervals to be in hours.
Thank you for any help in advance.
P.S. The datatype of ATTR_VALUE is VARCHAR2(150). A sample result of e.last_time is 2016-09-05 22:43:81796
"its VARCHAR2(150). That means I need to convert that to date"
ATTR_VALUE is a string so yes you need to convert it to the correct type before attempting to compare it with another datatype. Given your sample data the correct type would be timestamp, in which case your subquery should be:
(
select to_timestamp(ATTR_VALUE, 'yyyy-mm-dd hh24:mi:ss.ff5') as last_time
from CONFIG
where ATTR_NAME='last_time'
and PROCESS_TYPE='new'
)
The assumption is that your sample is representative of all the values in your CONFIG table for the given keys. If you have values in different formats your query will break on some other way: that's the danger of using this approach.
So finally after lots of trial and errors I got this one
1. Turns out initially the error was because the data_type of e.last_time was VARCHAR(150).
To find out the datatype of a given column in the table I used
desc <table_name>
which in my case was desc CONFIG
2. To convert VARCHAR to system time I have two options to_timestamp and to_date. If I use to_timestamp like
select round((systimestamp - to_timestamp(e.last_time,'YYYY-MM-DD HH24:MI:SSSSS')) * 24, 2) as lag
from (
select ATTR_VALUE as last_time
from CONFIG
where ATTR_NAME='last_time'
and PROCESS_TYPE='new'
) e;
I get an error that round expects NUMBER and got INTERVAL DAY TO SECONDS since the difference in date comes out to be like +41 13:55:20.663990. To convert that into hour would require a complex logic.
An alternative is to use to_data which I preferred and used it as
select round((sysdate - to_date(e.last_time,'YYYY-MM-DD HH24:MI:SSSSS')) * 24, 2) as lag
from (
select ATTR_VALUE as last_time
from CONFIG
where ATTR_NAME='last_time'
and PROCESS_TYPE='new'
) e;
This returns me the desired result i.e. the difference in hours rounded off to 2 floating digits

Oracle convert RAW to date format

I have a RAW field in my Oracle database that represents the date of user registered in system.
The value is something like 24E2321A0000000000 However I need convert the value to the date it represents (etc 2008-12-25 15:04:31).
I tried with totimestamp (see this sqlfiddle) but that didn't work.
Maybe this will help:
SELECT utl_raw.cast_to_binary_integer('24E2321A0000000000') raw_to_int
FROM dual
/
Output is 36. I'm not sure if you need days or hours. Next example is about adding 36 hours to SYSDATE:
-- SYSDATE + 36/24 --
SELECT SYSDATE+(utl_raw.cast_to_binary_integer('24E2321A0000000000')/24) my_date
FROM dual
/
MY_DATE
---------------------
12/13/2013 4:29:22 AM
please try one
declare
d date;
begin
dbms_stats.convert_raw_value (hextoraw('7876070A010101'), d);
dbms_output.put_line (d);
end;

I have 2 date fields and I want records that fall into 1 or both

I have 2 date fields and I am trying to use OR in the where clause. As an example,
Select customer_records.customer_id, customer_records.join_date, rejected_customers.rejected_date, status_lookup.status_description
From customer_records, rejected_customers, status_lookup
Where status_lookup.status_id(+) = customer_records.status_id and customer_records.customer_id = rejected_customers.customer_id
and (customer_records.join_date between to_date('01-10-2012','dd-mm-yyyy') and to_date('01-11-2012','dd-mm-yyyy') or rejected_customers.rejected_date between to_date('01-10-2012','dd-mm-yyyy') and to_date('01-11-2012','dd-mm-yyyy')
so, the basic outcome should be, I want customer_id's when the join date OR the rejected date falls into my date fields. I can't seem to get it to work, any help appreciated, thanks!
Select cr.customer_id, cr.join_date, rej.rejected_date
from customer_records cr left join rejected_customers rej on cr.customer_id=reg.customer_id
where (cr.join_date between to_date('01-10-2012','dd-mm-yyyy') and to_date('01-11-2012','dd-mm-yyyy')) or (rej.rejected_date between to_date('01-10-2012','dd-mm-yyyy') and to_date('01-11-2012','dd-mm-yyyy'))
When you say you can't seem to get it to work, I presume you run the query and you don't get the expected results and you don't get any errors.
Sometimes, some date fields are stored in the database with time fractions. so you need to use "trunc" function. See this example in Oracle database:
SQL> select to_char(sysdate, 'dd/mm/yyyy hh:mi:ss') date_no_trunc from dual;
DATE_NO_TRUNC
-------------------
28/03/2013 10:04:27
SQL> select to_char(trunc(sysdate), 'dd/mm/yyyy hh:mi:ss') date_with_trunc from dual;
DATE_WITH_TRUNC
-------------------
28/03/2013 12:00:00
SQL>
So you need to change your query to be like this:
Select c.customer_id,
c.join_date,
r.rejected_date
From customer_records c,
rejected_customers r
Where c.customer_id = r.customer_id
and ( trunc(c.join_date) between to_date('01-10-2012','dd-mm-yyyy') and to_date('01-11-2012','dd-mm-yyyy')
or
trunc(r.rejected_date) between to_date('01-10-2012','dd-mm-yyyy') and to_date('01-11-2012','dd-mm-yyyy')
)
Also, it's always a good idea to give long table names aliases, this makes your query shorter and uses less memory.

SQLite Order By Date1530019888000

Every record in my SQLite database contains a field which contains a Date stored as a string in the format 'yyyy-MM-dd HH:mm:ss'.
Is it possible to query the database to get the record which contains the most recent date please?
you can do it like this
SELECT * FROM Table ORDER BY date(dateColumn) DESC Limit 1
For me I had my query this way to solve my problem
select * from Table order by datetime(datetimeColumn) DESC LIMIT 1
Since I was storing it as datetime not date column
When you sure the format of text field is yyyy-MM-dd HH:mm:ss (ex.: 2017-01-02 16:02:55), So It works for me simply:
SELECT * FROM Table ORDER BY dateColumn DESC Limit 1
Without any extra date function!
You need to convert it to unix timestamp, and then compare them:
SELECT * FROM data ORDER BY strftime('%s', date_column) DESC
But this can be pretty slow, if there are lots of rows.
Better approach would be to store unix timestamp by default, and create an index for that column.
You can convert your column sent_date_time to yyyy-MM-dd format and then order by date:
1) substr(sent_date_time,7,4)||"-"||substr(sent_date_time,1,2)||"-"||substr(sent_date_time,4,2) as date
2) order by date desc
In my case everything works fine without casting column to type 'date'. Just by specifying column name with double quotes like that:
SELECT * FROM 'Repair' ORDER BY "Date" DESC;
I think SQLite makes casting by itself or something like that, but when I tried to 'cast' Date column by myself it's not worked. And there was no error messages.
You can also use the following query
"SELECT * FROM Table ORDER BY strftime('%Y-%m-%d %H:%M:%S'," + dateColumn + ") DESC Limit 1"
I found this ugly hack worked.
select *, substr(date_col_name,7,4)as yy,
substr(date_col_name,4,2) as mm,
substr(date_col_name,1,2) as dd
from my_table
order by yy desc,mm desc,dd desc
it would be better to convert the text column to date field type, but I found that did not work reliably for me.
If you do a lot of date sorting/comparison, you may get better results by storing time as ticks rather than strings, here is showing how to get 'now' in ticks with:
((strftime('%s', 'now') - strftime('%S', 'now') + strftime('%f', 'now')) * 1000)
(see https://stackoverflow.com/a/20478329/460084)
Then it's easy to sort, compare, etc ...
This will work for both date and time
SELECT *
FROM Table
ORDER BY
julianday(dateColumn)
DESC Limit 1

Teradata - Invalid Date supplied for FIELD

I'm trying to query a table that has a varchar(100) "VALUE" column. This column can hold anything from a letter, a number or, in this case, a date.
The date will always be entered in the table as 'YYYY-mm-dd'. However, when I run the following query:
select * from myTable
where VALUE = '2009-12-11' (Date, Format 'yyyy-mm-dd')
I receive the following error:
Invalid date supplied for myTable.VALUE.
Example of the value table:
(1,'122')
(2,'red')
(3,'2009-12-11')
Any ideas as to what might be causing this?
Thanks!
if the data type is declared as varchar, it should just treat it like a string.
try not specifying anything about the date format, like
select * from myTable
where VALUE = '2009-12-11'
If you run an explain on the query, you can see that it's casting value to date before comparing against your supplied value. If you have another column that accurately records the type of what's in VALUE, you can add that to the where clause and you will no longer get the error (see below). Otherwise, go with Beth's recommendation.
select * from myTable
where VALUE = '2009-12-11' (Date, Format 'yyyy-mm-dd')
and VALUE_TYPE = 'DATE';
Teradata internal date calculation is (year - 1900) * 10000 + (month * 100) + day.
So if date is 02/11/2009 (2nd November 2010) then
=(2009-1900) * 10000 + (11 * 100) + 2
=109 * 10000 + 1100 + 2
=1090000 + 1100 + 2
=1090000
1100
2
----------
1091102
----------
So 2nd november 2009 is stored in Teradata as 1091102.
You can extract it in required format by casting (as u have it in varchar). Hope this helps.
Is it possible that VALUE is a reserved word in Teradata?
If so, you need to put that into double quotes:
select *
from myTable
where "VALUE" = '2009-12-11'