I've setup a dynamic action to run javascript code to pick either "A" or "B" based on what time it is. If the time is between 07:00 (h24:mm) and 17:50 (h24:mm) it should set the value to "A", else "B".
I've got a field (P4_TIME_RECORDED) on the form that pulls the current time using this code
select to_char(systimestamp,'hh24:mm') as timestamp from dual
and a field (P4_SHIFT) that is a checkbox between A and B. checkbox example
Any help would be awesome.
Based on the explanation in your question I'd go for a slightly different approach.
The value needs to be Shift A or Shift B. A radio group seems to be most appropriate there, since only one value can be selected at any time.
The value is based on sysdate, not on something that is changed after the page is rendered, so a dynamic action is overkill. Instead you can use a computation to get the value at page rendering time.
So this is what I'd do
Create a page item P4_SHIFT of type radio group (Static values, values A and B)
Add a computation on P4_SHIFT with processing point before regions of type Expression with source
CASE
WHEN TO_CHAR(SYSDATE,'HH24MI') BETWEEN '0700' AND '1750'
THEN 'A'
ELSE 'B'
END
I'd create a DA and set it to be fired on page load.
set value -> from SQL Query
my query would be something like
select
case
when sysdate between time_1 and time_2
then 'A'
else 'B'
end as res
from(
select
trunc(sysdate) + interval '7' hour as time_1,
trunc(sysdate) + interval '17' hour + interval'50' minute as time_2
from dual)
and ofcourse, affected element has to be set as your cbx item.
Related
I have a simple table, which is queried from my backend every minute.
id (int) | phone_number (string) | start (timedatestamp) | period (string) | occurances (int)
I make an sql query, which runs every minute, and returns the results. It's selects all phone_numbers which start this minute.
SELECT * FROM table
WHERE start >= date_trunc('minute', now()) and
start < date_trunc('minute', now()) + interval '1 minute'
as results
This runs fine, but I need to update the table as well, based on this select results.
There are two parts to this:
For each selected row, I need the occurrences to decrement by 1 and update the database with this
For each selected row, if the periodicity='MONTHLY", I need the start column to change to the date and time exactly a month from now.
Is it possible to do this in one SQL statement? Any help or examples are greatly appreciated :)
Yes and you can do so directly. The only 'twist' is when a column in mentioned in the SET clause Postgres always writes the Rvalue. When you desire to conditionally update a column you set the Rvalue to the existing value when the condition is not meet. See fiddle here.
update atable
set occurances = occurances-1
, start_tm = case when period_txt = 'Monthly'
then now()+interval '1 month'
else start_tm
end
where date_trunc('minute',start_tm) = date_trunc('minute',now());
SELECT SERIES_ROUND(TO_TIMESTAMP(DATE_TIME,'YYYYMMDDHH24MISS'),'INTERVAL 30 MINUTE') as TIME
returns a result like "Mon Nov 02 2020 00:00:00 GMT+0100 (CET)"
what i need is to return shift name
if time between 08:00:00 and 16:30:00 return SHIFT A
if time between 16:30:00 and 00:15:00 return SHIFT B
if time between 00:15:00 and 08:00:00 return SHIFT C
any help appreciated
Something like the following should work:
SELECT CASE WHEN CAST(TO_TIMESTAMP(DATE_TIME,'YYYYMMDDHH24MISS') AS TIME) BETWEEN TO_TIME ('08:00:00', 'HH24:MI:SS') AND TO_TIME ('16:30:00', 'HH24:MI:SS') THEN 'Shift A'
WHEN CAST(TO_TIMESTAMP(DATE_TIME,'YYYYMMDDHH24MISS') AS TIME) BETWEEN TO_TIME ('00:15:00', 'HH24:MI:SS') AND TO_TIME ('08:00:00', 'HH24:MI:SS') THEN 'Shift C'
ELSE 'Shift B' END
This reads a bit like a query that should process the clock-in times of workers or something similar.
Therefore I used clock_ins as the name for the timestamped events in my example code.
To make this work correctly, it helps to make the different computations and data type conversions step by step:
WITH clock_ins AS (
SELECT 1 AS ID, to_timestamp('20200101080012', 'YYYYMMDDHH24MISS' ) AS DATE_TIME FROM DUMMY
UNION ALL
SELECT 2 AS ID, to_timestamp('20200101043135', 'YYYYMMDDHH24MISS' ) AS DATE_TIME FROM DUMMY
UNION ALL
SELECT 3 AS ID, to_timestamp('20200101120056', 'YYYYMMDDHH24MISS' ) AS DATE_TIME FROM DUMMY
UNION ALL
SELECT 4 AS ID, to_timestamp('20200101170012', 'YYYYMMDDHH24MISS' ) AS DATE_TIME FROM DUMMY
),
clock_ins_rounded AS (
SELECT
ID
, SERIES_ROUND(DATE_TIME,'INTERVAL 30 MINUTE') AS clock_in
, to_time(SERIES_ROUND(DATE_TIME,'INTERVAL 30 MINUTE')) AS clock_in_time
FROM
CLOCK_INS)
SELECT
id
, CLOCK_IN
, clock_in_time
, CASE
WHEN clock_in_time BETWEEN to_time('08:00:00') AND to_time('16:30:00') THEN
'SHIFT A'
WHEN ( clock_in_time >= to_time('16:30:00')
OR clock_in_time <= to_time('00:15:00')) THEN
'SHIFT B'
WHEN clock_in_time BETWEEN to_time('00:15:00') AND to_time('08:00:00') THEN
'SHIFT C'
ELSE
'NO SHIFT'
END AS SHIFT
FROM
clock_ins_rounded;
ID|CLOCK_IN |CLOCK_IN_TIME|SHIFT |
--|-------------------|-------------|-------|
1|2020-01-01 08:00:00| 08:00:00|SHIFT A|
2|2020-01-01 04:30:00| 04:30:00|SHIFT C|
3|2020-01-01 12:00:00| 12:00:00|SHIFT A|
4|2020-01-01 17:00:00| 17:00:00|SHIFT B|
The first WITH-clause CLOCK_INS generates the test data and includes at least one case for every rule the OP mentioned.
The second WITH-clause CLOCK_INS_ROUNDED performs the "rounding" to the 30 minutes intervals via the SERIES_ROUND function (good choice!). It also takes the result from this rounding and creates a time of day version from it via the TO_TIME() function. This column is then made available as CLOCK_IN_TIME.
The final and main SELECT clause projects the computed CLOCK_IN timestamp, the CLOCK_IN_TIME column, and also the assigned shifts.
The shifts are assigned via a CASE statement. To make this work correctly it is important to use TIME data types for the comparisons. Leaving out the TO_TIME( ) conversion for each of the conditions would lead to implicit type conversion and the comparison would be calculated as string comparisons which is NOT what you want for this use case.
The other important bit to notice is the rule for SHIFT B. This rule describes an interval between a time before and a time after midnight. As we are dealing with instants of time (actually not even that - it's just time of day data we use) here and not with intervals the BETWEEN comparison would not work correctly for the case of BETWEEN 16:30 AND 00:15.
Therefore, we need to take care of this in the code and translate this condition to LARGER (LATER) THAN 16:30 OR SMALLER (EARLIER) THAN 00:15.
Finally, it is a good idea to include an others branch in CASE statements, so that it is easy to detect data that is not handled by any rule or when rules are not "catching" data that they should have caught.
In summary, these are the main points to consider for this requirement:
implement one computation at a time and avoid overly nested expressions (to make the code easier to be read and understood)
use an appropriate data type for the comparison semantic (e.g. use a TIME data type when using time comparisons like "earlier" or "later). This includes both the data to be processed as well as the comparison data in the code.
when dealing with time-related data types, make sure to understand the differences between date-time, intervals, and time-of-day data
when using CASE statements, include an others case for data that is not handled by the other rules
I am trying update a column called scheddate, which is a Date datatype, based on the value from another column, transleadtime.
transleadtime holds the number of minutes as a Number datatype.
What is the best way to add minutes to a date variable? Here is what I have tried so far:
'UPDATE scpomgr.schedrcpts sr
SET sr.scheddate = (SELECT sr.scheddate + MAX(n.transleadtime / 1440)
FROM scpomgr.network n
WHERE n.source = sr.loc);'
You can try use the dateadd function here. This function takes a specific value, and adds it to a specified date. You can add days, years, minutes, hours, and so on. In your case, you want to add minutes, and since you are adding to the already existing scheddate, you will use that as a parameter.
Here's what the syntax may look like:
UPDATE scpomgr.schedrcpts sr
SET sr.scheddate = dateadd(
minute,
(SELECT n.transleadtime FROM scpomgr.network n WHERE n.source = sr.loc),
(SELECT sr.scheddate)
);
This will add minutes (specified by the first parameter), to the sr.scheddate (specified by the third parameter). The minutes that will be added are the n.translead time (specified by the second parameter).
Right now, this makes the assumption that selecting the sr.scheddate and select n.transleadtime that you have will only return 1 value. If they return more, you may have to adjust your where statement or limit the result set.
I also took out the NVL function, but if you want to protect against null values I would put them in the second and/or third parameters. Definitely in the second, but if your scheddate column doesn't accept null values, then you won't need it.
UPDATE scpomgr.schedrcpts sr
SET sr.scheddate = dateadd(
minute,
NVL((SELECT n.transleadtime FROM scpomgr.network n WHERE n.source = sr.loc), 0),
(SELECT sr.scheddate)
);
I can't test this at the moment, so it may take some tweaking, but start there and let me know how we can improve it.
EDIT
If you're looking for the highest transleadtime, I do think the MAX function would be the simplest way. Try adjusting the subquery in the second parameter to:
SELECT MAX(n.transleadtime) FROM scpomgr.network n WHERE n.source = sr.loc
I am trying to get the highest value from a table, but the value must have been set within the last 5 days.
The query below seems to work but how do I write it in Hibernate Query Laguage, HQL?
SELECT MAX(my_value) as my_value FROM Character WHERE create_date > now() + interval '-5 day'
I have tried to make the above sql statement as a native query but then it complains about that some fields coudln´t be found (I guess that Hibernate tries to set all the fields in the entity but the above sql just returns one column/row called 'my_value').
you can do it like below
first get the date for last 5th day using java
Calendar c = Calendar.getInstance();
c.add(Calendar.DAY_OF_YEAR, -6);
Date d = c.getTime();
select c.my_value from Character c
where c.my_value =
(select max(cc.my_value) from Character cc where cc.create_date > d )
make sure Character class has the attributes my_value and create_date correctly, and use them as it is in Character entity class not as it is in table.
in our Application we have two columns at the moment. 1 column with the datetime of an event and 1 column with the datetime how much earlier the alarm should go off. Now we have a new one and thats the exact datetime when the alarm goes off.
I know how I can calculate this for only 1 row, but not for all
select to_date('12/30/1899', 'MM/DD/YYYY') + (select termin_start - alarmvorlauf from termine where id = 1013) from dual
How can I modify the sql so it can update every row in the table 'termine'?
Not sure if I completely understand you, but my guess:
UPDATE termine SET alarm_goes_off = (to_date('12/30/1899', 'MM/DD/YYYY') + (termin_start - alarmvorlauf));
Please add more detail if this is not what you need.