I am trying to run following query on oracle at PL/SQL developer to select a list of time slots between current time and end of the day:
SELECT T.VISIT_DATE
FROM REGISTRATION.VU_SCHEDULE T
WHERE T.VISIT_DATE BETWEEN TO_DATE(SYSDATE, 'DD-MON-YYYY HH24:MI:SS')
AND TO_DATE('27-MARCH-2020 23:59:59', 'DD-MON-YYYY HH24:MI:SS')
ORDER BY VISIT_DATE
but it gives me result of whole day instead of current time of day
VISIT_DATE
1 3/27/2020 9:00:00 AM
2 3/27/2020 9:15:00 AM
3 3/27/2020 9:30:00 AM
4 3/27/2020 9:45:00 AM
5 3/27/2020 10:00:00 AM
6 3/27/2020 10:15:00 AM
7 3/27/2020 10:30:00 AM
8 3/27/2020 10:45:00 AM
9 3/27/2020 11:00:00 AM
10 3/27/2020 11:15:00 AM
11 3/27/2020 11:30:00 AM
12 3/27/2020 11:45:00 AM
e.g if current time is 11:00 AM then it should give result from current time.
I've tried trunc(sysdate) but it doesn't work
NOTE:
The condition must have date and time from now to the end of the day with format.
must have date and time from now to the end of the day with format.
You could do:
where t.visit_date >= sysdate and t.visit_date < trunc(sysdate) + 1
Rationale:
sysdate gives you the current date/time, that represents the lower bound of the interval
trunc(sysdate) is the beginninig of the current day (today at midnight), to which you can add 1 to get the beginning of the next day; this is the (exclusive) upper bound of the range
Note that there is no point applying to_date() to function sysdate, that produces a date alreay.
Related
I have hours and minutes in different columns like below
Hour of Day
Minute of Day
10
50
15
00
By using these values I need the exact day time like the result of above table should be
Expected Result
10:50 AM
03:00 PM
How can I achieve this by using Oracle or SQL? Can someone please help me onto this.
Here's one option - first create a DATE value (concatenate hours and minutes, apply appropriate format model); for the final result, apply TO_CHAR to it, again with desired format.
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> with test (hour, minute) as
2 (select '10', '50' from dual union all
3 select '15', '00' from dual
4 )
5 select hour, minute,
6 to_date(hour||':'|| minute, 'hh24:mi') date_value,
7 to_char(to_date(hour||':'|| minute, 'hh24:mi'), 'hh:mi am') result
8 from test;
HO MI DATE_VALUE RESULT
-- -- ------------------- ------------------------------
10 50 01.03.2022 10:50:00 10:50 AM
15 00 01.03.2022 15:00:00 03:00 PM
SQL>
Project: BIRT
Datasource: Amazon Redshift
I want to generate a Data Set with value of:
00:00:00
1:00:00
2:00:00
3:00:00
4:00:00
5:00:00
6:00:00
7:00:00
8:00:00
9:00:00
10:00:00
11:00:00
12:00:00
13:00:00
14:00:00
15:00:00
16:00:00
17:00:00
18:00:00
19:00:00
20:00:00
21:00:00
22:00:00
23:00:00
23:59:59 //the last value should display like this
I was able to generate a series of 24hours with 1 hr interval, but I need to make the last one's value as 23:59:59
Query to generate 24 hours with 1 hour interval:
SELECT start_date + gs * interval '1 hour' as times
FROM (
SELECT '2019-05-21 00:00:00'::timestamp as start_date, generate_series(1,24, 1) as gs)
How is that?
Thanks
Updating your query, just adding a if for the last hour:
SELECT
start_date + gs * interval '1 hour'
- if(gs=24, interval '1 second', interval '0 second') as times
FROM (
SELECT
'2019-05-21 00:00:00'::timestamp as start_date
, generate_series(1,24, 1) as gs
)
I think too much about this, the simplest way to achieve this is just add a default value on the report parameter , if you're going to use the data set in the report parameter
or with this:
SELECT start_date + gs * interval '1 hour' as times
FROM (
SELECT '2020-01-01 00:00:00'::timestamp as start_date, generate_series(1,24, 1) as gs)
union
select '2020-01-01 23:59:59'::timestamp as start_date
I have a question and hopefully someone can help, because i have been stuck on this for a long time.
I have a column with remaining minutes for a task to expire and i want to calculate when this task will expire within the business days timeframe starting from the current sysdate day lets say weekdays from 09:00 to 17:00.
| Task No | Minutes Remaining | Expiration date |
| Task1 | 1800 | 27-10-16 9:45 AM |
| Task2 | 3400 | 28-10-16 9:45 AM |
| Task3 | 400 | 29-10-16 9:45 AM |
| Task4 | 180 | 30-10-16 9:45 AM |
| Task5 | 8400 | 31-10-16 9:45 AM |
| Task6 | 5000 | 1-11-16 9:45 AM |
OK, this was a fun problem. To summarize: You are given a date (which in Oracle always includes the time-of-day) from which you start measurement, and an initial duration in minutes. You need to find the expiration date (meaning date and time-of-day as always), which is calculated by adding the duration in minutes to the "clock-starting" date, but the clock should only run during business hours - 9 to 17, Monday to Friday only (not on weekends).
I assume if the "minutes remaining" is 0, then the expiration should be the same as the "clock-starting" date if it falls within work hours, or 9 am on the next work day otherwise.
To understand the solution, let's break it down in two parts. First let's consider a very special case: the "clock starts" on a Monday at 9 am. Then break down minutes remaining into an integer multiple of 2400 (5*8*60 = 2400 minutes in a full work week), plus an integer multiple of 480 from what's left (480 minutes to a work day), plus whatever is left, if anything. Then: the expiration date is the "clock-starting" date, plus however many weeks, plus however many whole days (between 0 and 4), plus the remaining minutes. One exceptional case here: if the "minutes remaining" is an exact multiple of 480 minutes, then expiration is at 5 pm on a certain work day, and not 9 am on the next work day. This requires special handling in the formula. All this is done in the outer query (at the bottom of the solution below).
Then we need to reduce the general case to this special case. This is done in the subquery prep in the solution. I simply increase the "minutes remaining" by the work minutes elapsed from 9 am on Monday at the beginning of the week. This is a relatively simple computation. Note that if the "clock starting" date is after 5 pm on a Friday (or any time on Saturday or Sunday), I must add exactly 2400 minutes, a full work week.
In the solution, I show a variety of "clock starting" dates, dt, and minutes remaining, rm. I tested a variety of situations, and I think the solution is correct, but you may want to test on more data (other situations I didn't include in the tests).
with
inputs ( task, min_rem, dt ) as (
select 'Task1', 1800, to_date('27-10-16 9:45 AM', 'dd-mm-yy hh:mi AM') from dual union all
select 'Task2', 3400, to_date('28-10-16 9:45 AM', 'dd-mm-yy hh:mi AM') from dual union all
select 'Task3', 400, to_date('29-10-16 3:45 AM', 'dd-mm-yy hh:mi AM') from dual union all
select 'Task4', 180, to_date('30-10-16 9:45 AM', 'dd-mm-yy hh:mi AM') from dual union all
select 'Task5', 8400, to_date('31-10-16 9:45 PM', 'dd-mm-yy hh:mi AM') from dual union all
select 'Task6', 5000, to_date('01-11-16 5:00 PM', 'dd-mm-yy hh:mi AM') from dual union all
select 'Task7', 0, to_date('01-12-16 5:00 PM', 'dd-mm-yy hh:mi PM') from dual
),
prep ( task, min_rem, dt, adj_min, adj_dt ) as (
select task, min_rem, dt,
min_rem + case when dt > trunc(dt, 'iw') + 5 + 17/24 then 2400
else (trunc(dt) - trunc(dt, 'iw')) * 480 +
least(480, greatest(0, 1440 * (dt - trunc(dt) - 9/24)))
end,
trunc(dt, 'iw') + 9/24
from inputs
)
select task, min_rem, dt,
adj_dt + 7 * trunc(adj_min / 2400)
+ case when adj_min/480 = trunc(adj_min/480)
then mod(adj_min, 2400) / 480 - 1 + 8/24
else trunc(mod(adj_min, 2400) / 480) + mod(adj_min, 480) / 1440
end as expiration
from prep
order by task
;
Output:
TASK MIN_REM DT EXPIRATION
----- ---------- ----------------- -----------------
Task1 1800 27-10-16 09:45 AM 01-11-16 03:45 PM
Task2 3400 28-10-16 09:45 AM 08-11-16 10:25 AM
Task3 400 29-10-16 03:45 AM 31-10-16 03:40 PM
Task4 180 30-10-16 09:45 AM 31-10-16 12:00 PM
Task5 8400 31-10-16 09:45 PM 24-11-16 01:00 PM
Task6 5000 01-11-16 05:00 PM 16-11-16 12:20 PM
Task7 0 01-12-16 05:00 PM 01-12-16 05:00 PM
7 rows selected
I need a oracle query which returns every minute between given two timestamps. I referred this Stack Overflow question.
Can we improve the same query?
To get all the minutes between two datetime elements using Row Generator technique, you need to convert the difference between the dates into the number of minutes. Rest remains same in the CONNECT BY clause.
For example, to get all the minutes between 11/09/2015 11:00:00 and 11/09/2015 11:15:00:
SQL> WITH DATA AS
2 (SELECT to_date('11/09/2015 11:00:00', 'DD/MM/YYYY HH24:MI:SS') date_start,
3 to_date('11/09/2015 11:15:00', 'DD/MM/YYYY HH24:MI:SS') date_end
4 FROM dual
5 )
6 SELECT TO_CHAR(date_start+(LEVEL -1)/(24*60), 'DD/MM/YYYY HH24:MI:SS') the_date
7 FROM DATA
8 CONNECT BY level <= (date_end - date_start)*(24*60) +1
9 /
THE_DATE
-------------------
11/09/2015 11:00:00
11/09/2015 11:01:00
11/09/2015 11:02:00
11/09/2015 11:03:00
11/09/2015 11:04:00
11/09/2015 11:05:00
11/09/2015 11:06:00
11/09/2015 11:07:00
11/09/2015 11:08:00
11/09/2015 11:09:00
11/09/2015 11:10:00
11/09/2015 11:11:00
11/09/2015 11:12:00
11/09/2015 11:13:00
11/09/2015 11:14:00
11/09/2015 11:15:00
16 rows selected.
Above, CONNECT BY level <= (date_end - date_start)*(24*60) +1 means that we are generating rows as many as the number (date_end - date_start)*(24*60) +1. You get 16 rows, because it includes both the start and end window for the minutes.
You can create like this if you want all minutes from sysdate to 15 NOV:
SELECT to_char(TRUNC(sysdate) + numtodsinterval(level - 1, 'minute'),
'dd.mm.yyyy hh24:mi') min
FROM dual
CONNECT BY LEVEL <=
(trunc((TO_DATE('16-NOV-2015','dd-mon-yyyy')) - sysdate) * 24 * 60);
you can also use below and give your values instead of systimestamp and systimestamp+1
select (systimestamp)+level/(24*60) as Rang_values
from
dual
connect by level
<=
(
select extract( minute from diff)+
extract(day from diff)*24*60 +
extract(hour from diff)*60 as diff
from
(
select systimestamp+1-systimestamp diff from dual
)
)
I have an sql query in which I need to select the records from table where the time is between 3:00 PM yesterday to 3:00 PM today if today's time is more than 3:00 PM.
If today's time is less than that, like if today's time is 1:00 PM. then then my query should take today's time as 1:00 PM (which should return me records).
I need to get the time between 3:00pm yesterday to 3:00pm today if todays time is more than 3:00pm
if todays time is less than 3:00pm then get the 3:00pm yesterday to current time today
The best way of handling this is to use an IF statement:
IF TO_CHAR(SYSDATE, 'HH24') >= 15 THEN
SELECT x.*
FROM YOUR_TABLE x
WHERE x.date_column BETWEEN TO_DATE(TO_CHAR(SYSDATE -1, 'YYYY-MM-DD')|| ' 15:00:00', 'YYYY-MM-DD HH24:MI:SS')
AND TO_DATE(TO_CHAR(SYSDATE, 'YYYY-MM-DD')|| ' 15:00:00', 'YYYY-MM-DD HH24:MI:SS')
ELSE
SELECT x.*
FROM YOUR_TABLE x
WHERE x.date_column BETWEEN TO_DATE(TO_CHAR(SYSDATE -1, 'YYYY-MM-DD')|| ' 15:00:00', 'YYYY-MM-DD HH24:MI:SS')
AND SYSDATE
END IF;
Conditional WHERE clauses are non-sargable.
Previously:
If I understand correctly, you want to get records within the last day. If the current time is 3 PM or later, the time should be set to 3 PM. If earlier than 3 PM, take the current time...
SELECT x.*
FROM YOUR_TABLE x
JOIN (SELECT CASE
WHEN TO_CHAR(SYSDATE, 'HH24') >= 15 THEN
TO_DATE(TO_CHAR(SYSDATE, 'YYYY-MM-DD')|| ' 15:00:00', 'YYYY-MM-DD HH24:MI:SS')
ELSE SYSDATE
END AS dt
FROM DUAL) y ON x.date_column BETWEEN dt - 1 AND dt
Note:
dt - 1 means that 24 hours will be subtracted from the Oracle DATE.
Reference:
TO_CHAR
TO_DATE
There is no need for an IF statement. This can be solved easily with simple SQL.
My table T23 has some records with dates; here is a sample with times at 3.00pm:
SQL> select id, some_date from t23
2 where to_char(some_date,'HH24') = '15'
3 /
ID SOME_DATE
---------- ---------
14 16-MAY-11
38 17-MAY-11
62 18-MAY-11
81 19-MAY-11
SQL>
As the current time is before 3.00pm my query will return records from 17-MAY and 18-MAY but not the record where ID=62...
SQL> select to_char(sysdate, 'DD-MON-YYYY HH24:MI') as time_now
2 from dual
3 /
TIME_NOW
-----------------
18-MAY-2011 10:45
SQL> select id, to_char(some_date, 'DD-MON-YYYY HH24:MI') as dt
2 from t23
3 where some_date between trunc(sysdate-1)+(15/24)
4 and least( trunc(sysdate)+(15/24), sysdate)
5 /
ID DT
---------- -----------------
38 17-MAY-2011 15:00
39 17-MAY-2011 16:00
40 17-MAY-2011 17:00
41 17-MAY-2011 18:00
42 17-MAY-2011 19:00
43 17-MAY-2011 20:00
44 17-MAY-2011 21:00
45 17-MAY-2011 22:00
46 17-MAY-2011 23:00
47 18-MAY-2011 00:00
48 18-MAY-2011 01:00
49 18-MAY-2011 02:00
50 18-MAY-2011 03:00
51 18-MAY-2011 04:00
52 18-MAY-2011 05:00
53 18-MAY-2011 06:00
54 18-MAY-2011 07:00
55 18-MAY-2011 08:00
56 18-MAY-2011 09:00
57 18-MAY-2011 10:00
20 rows selected.
SQL>