I am trying to do a case when on one of my columns, but the time has to be between two times during the week and different on the weekends. So if sched_time is between 8:30:00 and 14:45:00 during the week (M-F) then 'ABC' else 'DEF'. The sched_time column looks like this 2020-03-27 09:29:00. Here is what I have so far:
SELECT Client_Last_Name,
Client_First_Name,
Sched_Time,
CASE WHEN Sched_time IS BETWEEN '08:30:00' AND '14:45:00'
THEN 'ABC'
ELSE 'DEF'
END
Field_Name,
Recoded_Response,
Dlsequence
FROM DAILY_LOG_CUSTOM_DATA
WHERE SERVICE_NAME = 'Medical'
AND FIELD_CATEGORY = 'Background Information'
AND Field_Name = 'Restraint?'
AND Recoded_Response = 1
And Sched_Time >= TRUNC(SYSDATE + 1, 'IW') - 8 AND
Sched_Time <= TRUNC(SYSDATE + 1, 'IW') - 1
Assuming that SCHED_TIME is of type DATE then you can take advantage of INTERVAL arithmetic:
SELECT Client_Last_Name,
Client_First_Name,
Sched_Time,
CASE
WHEN Sched_time BETWEEN TRUNC(SCHED_TIME) + INTERVAL '8' HOUR + INTERVAL '30' MINUTE
AND TRUNC(SCHED_TIME) + INTERVAL '14' HOUR + INTERVAL '45' MINUTE AND
TO_CHAR(SCHED_TIME, 'DY') IN ('MON', 'TUE', 'WED', 'THU', 'FRI')
THEN 'ABC'
ELSE 'DEF'
END
Field_Name,
Recoded_Response,
Dlsequence
FROM DAILY_LOG_CUSTOM_DATA
WHERE SERVICE_NAME = 'Medical'
AND FIELD_CATEGORY = 'Background Information'
AND Field_Name = 'Restraint?'
AND Recoded_Response = 1
AND Sched_Time >= TRUNC(SYSDATE + 1, 'IW') - 8 AND
Sched_Time <= TRUNC(SYSDATE + 1, 'IW') - 1
You can use to_char(). Assuming English language settings:
CASE WHEN TO_CHAR(Sched_time, 'HH24:MI:SS') BETWEEN '08:30:00' AND '14:45:00' AND
TO_CHAR(Sched_time, 'DY') NOT IN ('SAT', 'SUN')
THEN 'ABC'
ELSE 'DEF'
END
You can adjust this to include international settings, so the value is in English -- or your native language -- if that is preferable.
Related
I want to calculate next business day in Oracle query. So on Monday - Thursday it should be sysdate+1, on Friday it should be sysdate+3, on Saturday it should be sysdate+2 and on Sunday it should be sysdate+1.
I want to do it dynamically, rather than have lots of where statements covering the different days.
where order_date = CASE WHEN (1 + TRUNC (SYSDATE) - TRUNC (SYSDATE, 'IW')) < 5
THEN TRUNC (SYSDATE) + 1
ELSE TRUNC (SYSDATE + 4), 'IW')
END
I found this from the answer Next business day (Monday - Friday) in Oracle? but it seems error in query and I can't work it out.
You can use to_char(sysdate, 'fmday') which returns the string name of the day:
where order_date =
case
when to_char(sysdate, 'fmday', 'nls_date_language=AMERICAN') = 'friday' then trunc(sysdate) + 3
when to_char(sysdate, 'fmday', 'nls_date_language=AMERICAN') = 'saturday' then trunc(sysdate) + 2
else trunc(sysdate) + 1
end
and better:
where order_date =
trunc(sysdate) + case
when to_char(sysdate, 'fmday', 'nls_date_language=AMERICAN') = 'friday' then 3
when to_char(sysdate, 'fmday', 'nls_date_language=AMERICAN') = 'saturday' then 2
else 1
end
to have the results from the statement, use below statement.
where order_date =
(Select
CASE WHEN (1 + TRUNC (SYSDATE) - TRUNC (SYSDATE, 'IW')) < 5
THEN TRUNC (SYSDATE) + 1
ELSE TRUNC ((SYSDATE + 4), 'IW')
END from dual);
How to check if my current time stamp is between a time range.
for ex: I want to check my current time(let's say 03:00 PM) falls between 06:00 PM and 07:00 PM.
How do I check this in Oracle?
SELECT CASE
WHEN SYSDATE - TRUNC( SYSDATE ) BETWEEN 17.5/24 AND 18.5/24
THEN 'Is between 17:30 and 18:30'
ELSE 'Not between 17:30 and 18:30'
END
FROM DUAL;
or
SELECT CASE
WHEN SYSDATE BETWEEN TRUNC( SYSDATE ) + INTERVAL '17:30' HOUR TO MINUTE
AND TRUNC( SYSDATE ) + INTERVAL '18:30' HOUR TO MINUTE
THEN 'Is between 17:30 and 18:30'
ELSE 'Not between 17:30 and 18:30'
END
FROM DUAL;
I'd use strings for the comparision:
select
case when to_char(sysdate, 'HH24:MI') >= '18:00'
and to_char(sysdate, 'HH24:MI') < '19:00' then 'YES' else 'NO'
end as in_time_range
from dual;
There is a column 'DateTime' that displays the Date and Time in 'YYYY/MM/DD HH24:MI:SS' format.
I need to display only the rows that has time in a particular range(2AM - 6AM) regardless of the particular date.
I have a code that only displays the time range(2AM - 6AM) for the particular day. I need to display the rows that falls in the past 7 days with the time range 2AM-6AM.
SELECT *
FROM <table_name >
WHERE DateTime BETWEEN TO_DATE (
TO_CHAR (TRUNC (SYSDATE), 'DD-MM-YYYY')
|| ' '
|| '02:00:00',
'DD-MM-YYYY HH24:MI:SS')
AND TO_DATE (
TO_CHAR (TRUNC (SYSDATE), 'DD-MM-YYYY')
|| ' '
|| '06:00:00',
'DD-MM-YYYY HH24:MI:SS')
ORDER BY 1 DESC
SELECT *
FROM your_table
WHERE TO_CHAR( DateTime, 'HH24MMSS' ) BETWEEN '020000' AND '060000'
AND DateTime >= TRUNC( SYSDATE ) - INTERVAL '7' DAY
AND DateTime < TRUNC( SYSDATE ) + INTERVAL '1' DAY
or
SELECT *
FROM your_table
WHERE DateTime BETWEEN TRUNC( DateTime ) + INTERVAL '2' HOUR
AND TRUNC( DateTime ) + INTERVAL '6' HOUR
AND DateTime >= TRUNC( SYSDATE ) - INTERVAL '7' DAY
AND DateTime < TRUNC( SYSDATE ) + INTERVAL '1' DAY
You need two conditions for that: one for the hour being between 02 and 05, and one for the day being in the last seven days:
SELECT *
FROM <table_name>
WHERE to_char(DateTime, 'HH') BETWEEN '02' and '05' AND
DateTime BETWEEN SYSDATE - 7 AND SYSDATE
ORDER BY 1 DESC
In this case, I think the easiest way is string comparison:
WHERE SUBSTR(DateTime, 12, 2) BETWEEN '02' and '05'
Note: Between is inclusive so this should get everything up to 05:59:59.
SELECT *
FROM <table_name >
WHERE DateTime BETWEEN TO_DATE (
TO_CHAR (TRUNC (SYSDATE)-7, 'DD-MM-YYYY')
|| ' '
|| '02:00:00',
'DD-MM-YYYY HH24:MI:SS')
AND TO_DATE (
TO_CHAR (TRUNC (SYSDATE), 'DD-MM-YYYY')
|| ' '
|| '06:00:00',
'DD-MM-YYYY HH24:MI:SS')
select * from table_name where to_char(datetime,'HH24')
between '2' and '6' and to_char(datetime,'dd-mon-yy')
between to_char(sysdate,'dd-mon-yy') and to_char(sysdate-7,'dd-mon-yy');
Can someone please help me with writing a CASE query. Using the column name PERFORM_DT_TM - date & time format "MM-DD-YYYY HH-MI-SS"
Table name PERFORM_RESULT
The result I want is something like this:
BETWEEN'06:00:00'AND'14:29:59' THEN 'First Shift'
BETWEEN'14:30:00'AND'22:59:59' THEN 'Second Shift'
BETWEEN '23:00:00' AND'05:59:59' THEN 'Third Shift'
ELSE 'UNKNOWN'
You can use to_char(PERFORM_RESULT, 'HH24:MI') to get the hours and minutes from the date; the seconds aren't needed for this.
For 23:00 to 05:59 you need to check two ranges, because BETWEEN doesn't know about clock wraparound, it's just doing a textual comparison.
SELECT CASE
WHEN to_char(PERFORM_DT_TM, 'HH24:MI') BETWEEN '06:00' AND '14:29' THEN 'First Shift'
WHEN to_char(PERFORM_DT_TM, 'HH24:MI') BETWEEN '14:30' AND '22:59' THEN 'Second Shift'
WHEN to_char(PERFORM_DT_TM, 'HH24:MI') BETWEEN '23:00' AND '23:59' THEN 'Third Shift'
WHEN to_char(PERFORM_DT_TM, 'HH24:MI') BETWEEN '00:00' AND '05:59' THEN 'Third Shift'
ELSE 'UNKNOWN'
END
You can also take advantage of the fact that cases are tested sequentially to simplify it, since you don't have to check the beginning of a range if that has been excluded by the previous case.
SELECT CASE
WHEN to_char(PERFORM_DT_TM, 'HH24:MI') <= '05:59' THEN 'Third Shift'
WHEN to_char(PERFORM_DT_TM, 'HH24:MI') <= '14:29' THEN 'First Shift'
WHEN to_char(PERFORM_DT_TM, 'HH24:MI') <= '22:59' THEN 'Second Shift'
WHEN to_char(PERFORM_DT_TM, 'HH24:MI') <= '23:59' THEN 'Third Shift'
ELSE 'UNKNOWN'
END
Assuming this is for Oracle, and assuming that the PERFORM_DT_TM column is datatype DATE...
We can use the TO_CHAR function to format the time portion. For example:
TO_CHAR( t.perform_dt_tm,'HH24:MI' )
And we can do string comparisons in a CASE expression. For example:
SELECT CASE
WHEN TO_CHAR(t.perform_dt_tm,'HH24:MI') >= '06:00'
AND TO_CHAR(t.perform_dt_tm,'HH24:MI') < '14:30'
THEN 'First Shift'
WHEN TO_CHAR(t.perform_dt_tm,'HH24:MI') >= '14:30'
AND TO_CHAR(t.perform_dt_tm,'HH24:MI') < '23:00'
THEN 'Second Shift'
WHEN TO_CHAR(t.perform_dt_tm,'HH24:MI') >= '23:00'
OR TO_CHAR(t.perform_dt_tm,'HH24:MI') < '06:00'
THEN 'Third Shift'
ELSE 'Unknown'
END AS which_shift
, t.perform_dt_tm
, ...
FROM ... t
NOTE: This is based on the assumption that datatype of the column is DATE, and that this is for Oracle. If the column is a different datatype, then we'd need to adjust how the "time" portion is extracted.
The TO_CHAR function is specific to Oracle. If this is for a database other than Oracle, we would need to adjust the expression that extracts the time portion. (e.g. DATE_FORMAT for MySQL)
An equivalent result can be obtained more concisely:
SELECT CASE
WHEN TO_CHAR(t.perform_dt_tm,'HH24') < '06:00'
THEN 'Third Shift'
WHEN TO_CHAR(t.perform_dt_tm,'HH24:MI') < '14:30'
THEN 'First Shift'
WHEN TO_CHAR(t.perform_dt_tm,'HH24') < '23:00'
THEN 'Second Shift'
WHEN TO_CHAR(t.perform_dt_tm,'HH24') < '24:00'
THEN 'Third Shift'
ELSE 'Unknown'
END AS which_shift
, t.perform_dt_tm
, ...
FROM ... t
Oracle Setup:
CREATE TABLE PERFORM_RESULT ( PERFORM_DT_TM DATE );
INSERT INTO PERFORM_RESULT
SELECT TIMESTAMP '2016-05-23 00:00:00' FROM DUAL UNION ALL
SELECT TIMESTAMP '2016-05-21 12:00:00' FROM DUAL UNION ALL
SELECT TIMESTAMP '2016-05-19 15:00:00' FROM DUAL;
Query 1 - Comparing using fractions of a day:
SELECT PERFORM_DT_TM,
CASE WHEN time >= 6/24 AND time < 14.5/24 THEN 'First Shift'
WHEN time >= 14.5/24 AND time < 23/24 THEN 'Second Shift'
ELSE 'Third Shift'
END AS shift
FROM (
SELECT PERFORM_DT_TM,
PERFORM_DT_TM - TRUNC( PERFORM_DT_TM ) AS time
FROM PERFORM_RESULT
);
Query 2 - Comparing using intervals:
SELECT PERFORM_DT_TM,
CASE WHEN time >= INTERVAL '6' HOUR
AND time < INTERVAL '14' HOUR + INTERVAL '30' MINUTE
THEN 'First Shift'
WHEN time >= INTERVAL '14' HOUR + INTERVAL '30' MINUTE
AND time < INTERVAL '23' HOUR
THEN 'Second Shift'
ELSE 'Third Shift'
END AS shift
FROM (
SELECT PERFORM_DT_TM,
NUMTODSINTERVAL( PERFORM_DT_TM - TRUNC( PERFORM_DT_TM ), 'DAY' ) AS time
FROM PERFORM_RESULT
);
(or you could just convert all the times to minute intervals - i.e. INTERVAL '360' MINUTE, INTERVAL '870' MINUTE and INTERVAL '1380' MINUTE as the boundaries)
Output:
(Both output the same results)
PERFORM_DT_TM SHIFT
------------------- ------------
2016-05-23 00:00:00 Third Shift
2016-05-21 12:00:00 First Shift
2016-05-19 15:00:00 Second Shift
Assuming PERFORM_DT_TM is in datetime datatype (as it should be), you don't need a format model like 'MM-DD-YYYY' or similar; and you are best off using numeric comparisons rather than lexicographic.
The time of day is PERFORM_DT_TM - trunc(PERFORM_DT_TM). trunc keeps the same date but truncates the time portion back to 00:00:00 AM, so the difference is just the time component of the datetime stored in PERFORM_DT_TM. However, this "time component" is expressed as a fraction of 1 day; to compare to hours, divide the hours by 24 (or alternatively, multiply the time differences by 24; I illustrate the first choice below).
Assuming your table name is MY_TABLE, your case expression can be written (using the "with clause" available in Oracle 11.1 and above) as follows:
with p as (
select PERFORM_DT_TM - trunc(PERFORM_DT_TM) as PERF_TM [, other columns]
from MY_TABLE
)
select [other columns, perhaps PERF_TM,]
case
when PERF_TM >= 6/24 and PERF_TM < 14.5/24 then "First Shift"
when PERF_TM >= 14.5/24 and PERF_TM < 23/24 then "Second Shift"
when PERF_TM < 6/24 or PERF_TM >= 23/24 then "Third Shift"
else "Error/Unknown"
end as SHIFT
from p;
I have a question which is divided in two parts
Part 1
How can I get the following set of records with sysdate as current week?
07-Apr-2013 - 13-Apr-2013
14-Apr-2013 - 20-Apr-2013
21-Apr-2013 - 27-Apr-2013
28-Apr-2013 - 04-May-2013
If week is past 07-Apr-2012 - 13-Apr-2013, then next four sets. So always it will have 4 weeks.
Part 2
and if current week falls within the range of dates i.e. 07-Apr-2012 - 13-Apr-2013, I would like to get Monday and Friday from the list.
How can I get the desired output?
I'm a little confused by the date ranges you provide in your example as the start date of each range is a Sunday in 2013 yet you show 2012 as the year. I am going to assume the 2012 is a typo.
Does this get you what you want?
select
case
when trunc(sysdate) between start_date and end_date
then to_char(start_date + 1, 'DD-MON-YYYY')
else to_char(start_date, 'DD-MON-YYYY')
end
|| ' - ' ||
case
when trunc(sysdate) between start_date and end_date
then to_char(end_date - 1, 'DD-MON-YYYY')
else to_char(end_date, 'DD-MON-YYYY')
end date_range
from
(
select
next_day(trunc(sysdate - 7 + ((level - 1) * 7)), 'SUN') start_date,
next_day(trunc(sysdate) + ((level - 1) * 7), 'SAT') end_date
from dual
connect by level < 5
)
If you want just the 4 weeks then you can do this
select
to_char(next_day(trunc(sysdate - 7 + ((level - 1) * 7)), 'SUN'), 'DD-MON-YYYY')
|| ' - ' ||
to_char(next_day(trunc(sysdate) + ((level - 1) * 7), 'SAT'), 'DD-MON-YYYY') date_range
from dual
connect by level < 5
Part 1 (4 weeks starting with the current week)
SELECT TO_CHAR(trunc(SYSDATE, 'DY')) || ' - ' || TO_CHAR(trunc(SYSDATE, 'DY')+ 6) from dual
UNION
SELECT TO_CHAR(trunc(SYSDATE, 'DY')+7) || ' - ' || TO_CHAR(trunc(SYSDATE, 'DY')+ 13) from dual
UNION
SELECT TO_CHAR(trunc(SYSDATE, 'DY')+14) || ' - ' || TO_CHAR(trunc(SYSDATE, 'DY')+ 20) from dual
UNION
SELECT TO_CHAR(trunc(SYSDATE, 'DY')+21) || ' - ' || TO_CHAR(trunc(SYSDATE, 'DY')+ 27) from dual
;
Part 2 Monday and Friday of the current week:
SELECT trunc(SYSDATE, 'DY')+1 "Monday", trunc(SYSDATE, 'DY')+5 "Friday"
FROM dual;
Here's SQL Fiddle.
select
max(trunc(sysdate) + level - 7) as sunday,
max(trunc(sysdate) + level - 2) as friday,
max(trunc(sysdate) + level - 1) as saturday
from dual
connect by level < 30
group by to_char(sysdate + level, 'iw')
having max(trunc(sysdate) + level - 1) <= sysdate + 27
order by 1
fiddle