SQL query data between dates, efficiency - sql

I'm trying to search through a fairly large (56m+ row) table using an SQL query. The complication to just being able to do some quick SQL query like this:
Select *COLUMNS*
From *Table*
Where *Conditions* And
LOG_ENTRY_TIMESTAMP between {StartDate} and {EndDate}
is that I need to pull the 23:00 - 24:00 hour from the day before {StartDate} without pulling the rest of the data from that date. {StartDate} and {EndDate} are user entered fields in a DATE format. LOG_ENTRY_TIMESTAMP is a TIMESTAMP data type.
Is there a more time-efficient way of doing this than having to do something like:
TRUNC(CAST(LOG_ENTRY_TIMESTAMP AS DATE), 'HH') BETWEEN {StartDate}-1/24 and {EndDate}+23/24
Data will look like:
ITEM LOG_ENTRY_TIMESTAMP
---- ----------------------------------
A 2/12/2018 10:02:19.214528 AM -0500
B 2/14/2018 11:02:19.224528 PM -0500
C 2/16/2018 01:02:19.412528 AM -0500
D 2/16/2018 11:02:19.412528 PM -0500
And if I search from {StartDate} = 2/15/2018 through {EndDate} = 2/16/2018, I want to capture B & C.

I would suggest:
Where *Conditions* And
LOG_ENTRY_TIMESTAMP between {StartDate} - 1/24 and {EndDate}

I need data from 11pm the night before until 11pm tonight
if I search from {StartDate} = 2/15/2018 through {EndDate} = 2/16/2018, I want to capture B & C.
Assuming LOG_ENTRY_TIMESTAMP is indexed you can utilise that with:
Where *Conditions* And
LOG_ENTRY_TIMESTAMP >= {StartDate} - 1/24 and
LOG_ENTRY_TIMESTAMP < {EndDate} + 23/24
Again assuming that the variables are actually dates with time set to midnight, {StartDate} - 1/24 gives you 23:00 on the day before that start date, and {EndDate} + 23/24 gives you 23:00 on the end date.
With your sample data in a CTE and the filter dates as date literals:
with your_table (item, log_entry_timestamp) as (
select 'A', to_timestamp_tz('2/12/2018 10:02:19.214528 AM -0500',
'MM/DD/YYYY HH:MI:SS.FF6 AM TZHTZM') from dual
union all select 'B', to_timestamp_tz('2/14/2018 11:02:19.224528 PM -0500',
'MM/DD/YYYY HH:MI:SS.FF6 AM TZHTZM') from dual
union all select 'C', to_timestamp_tz('2/16/2018 01:02:19.412528 AM -0500',
'MM/DD/YYYY HH:MI:SS.FF6 AM TZHTZM') from dual
union all select 'D', to_timestamp_tz('2/16/2018 11:02:19.412528 PM -0500',
'MM/DD/YYYY HH:MI:SS.FF6 AM TZHTZM') from dual
)
select *
from your_table
where LOG_ENTRY_TIMESTAMP >= date '2018-02-15' - 1/24
and LOG_ENTRY_TIMESTAMP < date '2018-02-16' + 23/24;
I LOG_ENTRY_TIMESTAMP
- ---------------------------------
B 2018-02-14 23:02:19.224528 -05:00
C 2018-02-16 01:02:19.412528 -05:00
But you need to verify what the actual data types are for the values being used for the variables, and whether any time zone conversion is being done, which could affect the range of values you actually match.

Related

I need help understanding why am I am not getting any results with below query

Using query #1 below I get the the following results
select DATE, count (DATE) from TABLE1
group by DATE
DATE
COUNT(DATE)
6/6/2022
6856
6/6/2022 2:06:10 PM
78895
6/6/2022 2:06:11 PM
90230
6/6/2022 2:06:12 PM
95693
6/6/2022 2:06:13 PM
94352
6/6/2022 2:06:14 PM
9101
6/27/2022
6854
6/27/2022 7:36:58 PM
6422
Using the above results, I am now trying to write a query which will only isolate the 6/27/2022 dates, which are the two line items at the bottom of my results. I've tried using a to_char function as well as Like function but all variations of the queries that I write result in "No Records". In other words, the query runs but I get no results.
Select * from TABLE where to_char(DATE) like '%06/27/2022%'
Can someone help me with this.
Thank you,
If your column is a DATE data type and you want all the values from one day then:
Select *
from table_name
where date_column >= DATE '2022-06-28'
and date_column < DATE '2022-06-29'
If you want all the values at a particular instant then:
Select *
from table_name
where date_column = DATE '2022-06-28' + INTERVAL '14:06:10' HOUR TO SECOND
or
Select *
from table_name
where date_column = TIMESTAMP '2022-06-28 14:06:10';
or
Select *
from table_name
where TO_CHAR(date_column, 'YYYY-MM-DD HH24:MI:SS') = '2022-06-28 14:06:10';
If your column is a string data type then use the TO_DATE function to convert it to a date data type and then use one of the queries above.
For example:
Select *
from table_name
where TO_DATE(string_column, 'MM/DD/YYYY HH12:MI:SS AM') >= DATE '2022-06-28'
and TO_DATE(string_column, 'MM/DD/YYYY HH12:MI:SS AM') < DATE '2022-06-29'

sysdate range to whole value

Is it possible to turn the current time stamp to a whole number?
Example: If sysdate returns 1/19/2022 5:36:49 PM can I turn that to 1/19/2022 5PM since it falls in the 5PM range.
Here is my query
Select FACILITY, TRK_ID, LOT_DTTM, IN_QTY
from TRK_ID_LOT
WHERE facility in 'DP1DM5'
and trk_id like ('AE%')
and lot_dttm > sysdate - 1
EXAMPLE:
Truncate it to hours:
SQL> select trunc(to_date('1/19/2022 5:36:49 PM', 'mm/dd/yyyy hh:mi:ss pm'), 'hh') res
2 from dual;
RES
----------------------
01/19/2022 05:00:00 PM
SQL>
If you want to update rows, do so using the same function:
update your_table set
date_column = trunc(date_column, 'hh');

Oracle DB Query Timestamp with Like and '%'

I want to list all records that whose TARGET_COMMIT field days between 10/Nov/2018 and 18/Nov/2018 at around 5.00 AM. I have been using this query:
select * from (select * from GGS_ADMIN.GGS_HEARTBEAT_HISTORY
where DELGROUP='REPDELTA' and TARGET_COMMIT between '10/Nov/2018'
and '18/Nov/2018') where TARGET_COMMIT like '%/Nov/2018 5:%:%.% AM';
Here is one record of my inner query result:
SBLPROF, EDELTA, 11/10/2018 5:56:22.064830 AM, 11/10/2018
5:56:27.495548 AM,
11/10/2018 5:56:24.731541 AM, 2.666711, 11/10/2018
5:56:26.305759 AM, REPDELTA , 5.430718, 3, 11/10/2018
5:56:22.820934 AM, 0, 14441, 0, 14441
And here "11/10/2018 5:56:27.495548 AM" is my TARGET_COMMIT field.
If use
select * from (select * from GGS_ADMIN.GGS_HEARTBEAT_HISTORY where
DELGROUP='REPDELTA' and TARGET_COMMIT between '10/Nov/2018' and
'18/Nov/2018') where TARGET_COMMIT like '11/10/2018 5:56:27.495548 AM'
instead of my previous query it matches and lists the result. Why I can't use the "like" function and "%" for timestamp?
By the way here is my dual result:
select sysdate from dual;
SYSDATE
11/18/2018 04:11:53 PM
1 row selected.
Thanks in advance!
You may use TIMESTAMP literal and EXTRACT.Preferably use >= and < instead of BETWEEN for ranges.
SELECT *
FROM ggs_admin.ggs_heartbeat_history
WHERE delgroup = 'REPDELTA' AND
target_commit >= TIMESTAMP '2018-11-10 00:00:00'
AND target_commit < TIMESTAMP '2018-11-18 00:00:00' + INTERVAL '1' DAY
AND EXTRACT ( HOUR FROM target_commit) = 5
If you want a desired format, you may also use
WHERE
target_commit >= TO_TIMESTAMP('10/Nov/2018','dd/mon/yyyy') AND
target_commit < TO_TIMESTAMP('18/Nov/2018','dd/mon/yyyy') + INTERVAL '1' DAY
AND EXTRACT ( HOUR FROM target_commit) = 5

date time filter in sql

I have a report to be generated every hour from a sql query.
The request here is to generate data from yesterday's night 8.00 pm till
today's 12 pm noon . I am using the below query but not getting correct data:
select * from roster_report where job_start > TRUNC(SYSDATE-1) + 20/24 ;
Suppose today's date is 29th April, the report generated on 29th april 11:15 pm is showing data of 29th april 8:00 pm to 11:15 pm correctly.
the data gets incorrect after 00:00 am where it fetches data of 29th april itself and not 30th april.
The query will be used after every hour to generate report.
I am running this in oracle sql developer.
For previous day 8 PM
SELECT to_char(trunc(SYSDATE -1) + 20/24,'mm/dd/yyyy hh24:mi:ss AM') FROM dual;
For Today's 12 PM
SELECT to_char(trunc(SYSDATE) + 12/24,'mm/dd/yyyy hh24:mi:ss AM') FROM dual;
Sample Query
WITH DATA AS
( SELECT 'text' col, SYSDATE create_date FROM dual
)
select *
from tw_logtable
where tw_logtable.created_datetime
BETWEEN (TRUNC(sysdate -1) + 20/24) AND (TRUNC(sysdate) + 12/24)
Try
WHERE
job_start >= ( TRUNC(SYSDATE-1) + INTERVAL '20' HOUR )
AND job_start <= ( TRUNC(SYSDATE) + INTERVAL '12' HOUR )
You could just use > or < if that suits your requirement. BETWEEN can also be used for simplicity if all you want is inclusive range.
Here you have two ways:
SELECT *
FROM ROSTER_REPORT
WHERE JOB_START BETWEEN (TRUNC(SYSDATE - 1) + 20/24)
AND TRUNC(SYSDATE) + 12/24 ;
or
SELECT *
FROM ROSTER_REPORT
WHERE JOB_START BETWEEN TO_DATE(TO_CHAR(SYSDATE-1,'DD/MM/RRRR')||' 20:00','DD/MM/RRRR HH24:MI')
AND TO_DATE(TO_CHAR(SYSDATE ,'DD/MM/RRRR')||' 12:00','DD/MM/RRRR HH24:MI');

Oracle Timestamp Conversion with Dates

Assuming this has a simple solution, but I can't find it.
I'm trying to do some logic on a DATE field in Oracle. My desire is to take a DATE field and subtract X hours from it.
For instance: SELECT A.MyDATE - 100 Hours from dual;
however, I need a result in a timestamp format 'YYYY-MM-DD hh:mm'.
I've tried CAST(A.MyDATE as TIMESTAMP) - NUMTODSINTERVAL(100/24,'day') however it didn't work.
I found out that the issue is that the MyDATE field when cast to a timestamp still contained some residual time elements. How can I reset these??
Thanks!
You can just do this with subtraction:
select a.MyDate - 100.0/24
To convert to varchar:
select to_char(a.MyDate - 100.0/24, 'YYYY-MM-DD')
And, if you want to get rid of that pesky time on the date:
select trunc(a.MyDate - 100.0/24) as JustTheDate
The formats and dates in my example can be changed to any other formats and dates:
SELECT To_Timestamp(To_Char(Sysdate - INTERVAL '100' HOUR, 'MM/DD/YYYY HH24:MI'), 'MM/DD/YYYY HH24:MI')
FROM dual
/
Output:
2/4/2013 10:18:00.000000000 AM
To remove time element add Trunc() to any of your dates...:
SELECT Trunc(To_Timestamp(To_Char(Sysdate - INTERVAL '100' HOUR, 'MM/DD/YYYY HH24:MI'), 'MM/DD/YYYY HH24:MI'))
FROM dual
/
Output: 2/4/2013
Conversion/Casting - when using other dates in place of sysdate then add formats as in my other examples:
SELECT CAST(SYSDATE AS TIMESTAMP) - INTERVAL '100' HOUR FROM dual
/
Output: 2/4/2013 10:26:35.000000000 AM
SELECT start_date tstamp_to_date, CAST(start_date AS timestamp) date_to_tstamp FROM
(
SELECT to_date(to_char(to_timestamp ('2013-02-07 10:07:47.000' , 'YYYY-MM-DD HH24:MI:SS.FF'),'DD-MON-YYYY HH24:MI:SS'), 'DD-MON-YYYY HH24:MI:SS') start_date
FROM dual
)
/
Output:
tstamp_to_date date_to_tstamp
-------------------------------------------------------
2/7/2013 10:07:47 AM 2/7/2013 10:07:47.000000 AM
In Oracle, a DATE always has a day and a time component. Depending on the tool you are using and your session's NLS_DATE_FORMAT, it is entirely possible that the tool may not display the time component when you look at the data. But that is simply a display question, it has no impact on the actual data.
If you want to subtract 100 hours from midnight on the day that MyDate represents
SELECT TRUNC(MyDate) - interval '100' hour
FROM dual
This will return a DATE. If you want to return a string in a particular format
SELECT TO_CHAR( TRUNC(MyDate) - interval '100' hour, 'YYYY-MM-DD hh:mi am' )
FROM dual
Note that I'm assuming that there was a typo in your question. I assume that you want to display the minutes after the hour (mi) rather than the month (mm).
I am trying to fetch the records which is older than 30 days (from Mod_date) and I am using the below query and it is returning all the data and I want only 30 days old data.
Sample :- Mod_date 03-NOV-12 12.00.00.000000000 AM
Query :-
select Mod_date from fil_cnfact where Mod_date <= sysdate -30 order by Mod_date asc ;