Compare 2 times in sql developer - sql

I have 2 columns in xyz table, as start_time and end_time in 2 different tables.
table 1 - start_time & end_time
table 2 - avg_start_time & avg_end_time.
I need to check whether start_time(table1) is greater than avg_start_time. some how I am not getting output, however I am getting the expected answer if I do the less than instead of greater than,
to_char(start_time,'hh24:mi:ss') < to_char(avg_start_time,'hh24:mi:ss') -- no output
to_char(start_time,'hh24:mi:ss') > to_char(avg_start_time,'hh24:mi:ss') --
table values output -
-- 20:11:04(start_time) 20:05:00(avg_start_time)

can you try MSSQL
CAST(start_timeas as time) < cast(avg_start_time as time)?
update answer
Oracle:
my idea is create new timestamps from date now and time from objects and that values compared
to_timestamp((to_char(trunc(sysdate),'dd.MM.yyyy') || ' ' || to_Char(start_timeas, 'hh24:mi:ss')),'dd.MM.yyyy hh24:mi:ss') < to_timestamp((to_char(trunc(sysdate),'dd.MM.yyyy') || ' ' || to_Char(avg_start_time, 'hh24:mi:ss')),'dd.MM.yyyy hh24:mi:ss')

Related

Rename Column name in Pivot query and format its time value in format HH:MM:SS

I am preparing one report for which I need to have sum of time taken by various processes in column 2.
I am sharing small snippet in which I am not able to figure out. Below is the query.
SELECT DISTINCT *
FROM CTE_NAME
PIVOT ( SUM(TIME) FOR ACTIVITY IN ( NULL
,Process 1
,Process 2
)
) order by 2 desc
Things to be noted:-
hours_diff is the value calculated in a CTE expression above this shared snippet
hours_diff is of date type.
Things to be done:-
It is required to change the Column name NULL to TOTAL_TIME
It is required to convert the value of TIME to HH:MM:SS
Things I have tried:-
I tried using SUM(TIME) AS TOTAL_TIME ... it didn't seem to work. Also after that I tried replacing NULL with TOTAL_TIME but it changed in a way that TIME values of Process 1 shifted towards column 2.
In order to convert the time value (which is in seconds). I have this previously used TO_CHAR(TRUNC(sec_diff/3600),'FM9900') || ':' || TO_CHAR(TRUNC(MOD(sec_diff,3600)/60),'FM00') || ':' || TO_CHAR(MOD(sec_diff,60),'FM00') as time_diff. But as I am unable to fetch the column from above snippet I am not able to convert the values to HH:MM:SS
If I convert the value of TIME inside CTE then SUM function in SELECT query throws error Invalid Number as the value being passed to SUM function is in format HH:MM:SS
For giving name to the column, you can provide name in IN list of PIVOT as follows:
SELECT DISTINCT *
FROM CTE_NAME
PIVOT ( SUM(TIME) FOR ACTIVITY
IN ( NULL as TOTAL_TIME, -- THIS
,Process 1
,Process 2
)
) order by 2 desc;
To calculate HH:MI:SS from seconds, use this in select.(works for seconds in diff is less than 86400(1 day)
TO_CHAR(TRUNC(SYSDATE) + INTERVAL '1' SECOND * YOUR_COLUMN_SECONDS, 'HH24:MI:SS')
Or following will work for any bigger values
Lpad(Trunc(your_column_seconds/86400),2,'0')
|| ':' ||
Lpad(Trunc(your_column_seconds/1440),2,'0')
|| ':' ||
Lpad(Trunc(your_column_seconds/60),2,'0')
Note: column name of seconds difference generated by pivot should be used in above expression.

Oracle SQL: check if time is between two instances (excluding dd/mm/yyyy)

I am building an Oracle APEX application in which journalists can bring in articles, which a director selects for a broadcast, along with a newsreader (who can read the articles if the broadcast is created). I am kind of stuck with the following:
I would like to create an Oracle SQL query which selects the first and last name of a record in the "user" table, when its availability (which is stored in another table, "Beschikbaarheid") meets the given circumstances (user begin time at broadcast day >= broadcast begin time AND user end time at broadcast day <= broadcast end time).
I myself have written the following query.
SELECT voornaam || ' ' || achternaam AS display_value, id AS return_value
FROM Gebruiker
WHERE id NOT IN (SELECT Nieuwslezerselectie.nieuwslezerid FROM Nieuwslezerselectie
WHERE -- other conditions
AND id IN (SELECT gebruikerid
FROM Beschikbaarheid
WHERE (dag = to_char(to_date(:P91_DATUM,'DD-MON-YYYY'),'Day'))
AND (to_date(:P91_BEGINTIJD,'HH24:MI') >= to_date(begintijd,'HH24:MI'))
AND (to_date(:P91_EINDTIJD,'HH24:MI') <= to_date(eindtijd,'HH24:MI'))
);
(Excuse me if you are having trouble reading this, I use Dutch naming. Feel free to ask if something is unclear.)
However, the APEX select list to which this query is linked is not showing anything if the newsreader is available at the time of the broadcast. I think the problem is "Begintijd" and "Eindtijd" are stored as time stamps, as the values should be date-independent (which time stamps are not), but I have no clue how to store them otherwise. As a varchar maybe?
I sincerely hope you have any ideas. Thank you in advance!
Luc
update 1
With help I have rewritten the query, it now looks like this:
AND id IN (SELECT gebruikerid
FROM Beschikbaarheid
WHERE (dag = to_char(to_date(:P91_DATUM,'DD-MON-YYYY'),'Day','NLS_DATE_LANGUAGE=Dutch'))
AND (
to_date('01-01-2000' || ' ' || to_char(to_timestamp(:P91_BEGINTIJD),'HH24:MI'),'DD-MM-YYYY HH24:MI')
BETWEEN
to_date('01-01-2000' || ' ' || to_char(begintijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
AND
to_date('01-01-2000' || ' ' || to_char(eindtijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
)
AND (
to_date('01-01-2000' || ' ' || to_char(to_timestamp(:P91_EINDTIJD),'HH24:MI'),'DD-MM-YYYY HH24:MI')
BETWEEN
to_date('01-01-2000' || ' ' || to_char(begintijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
AND
to_date('01-01-2000' || ' ' || to_char(eindtijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
)
);
However, I am now getting the ORA-01840: input value not long enough for date format error when trying to access the page. I haven't discovered what causes that error yet. Does anyone have any clues?
update 2
Now I am confused. It turned out I didn't need to_char etc. for my page variables, so I removed those (to_char etc.). Now I am normally send to the correct page, but the last value I entered in the "set these items / with these values" text fields on the previous page, isn't send. This is what I have in these text fields right now:
In this image, P85_BEGINTIJD isn't send. I also switched the values around, but that didn't make a difference. Is there a limit to the amount of values you can send with a request, or something?
Do not use timestamps. se a date field, which includes date and time,
more info about date fields in oracle:
Oracle Data types, see paragraph Overview of DATE Datatype
If I got it right you have two columns with data type TIMESTAMP and you need to constraint it with a parameter, but using only the hour an minute part of it.
The simplest possible way to do it is use a string parameter in format HH:MI
select begintijd, to_char(begintijd,'HH24:MI') begintijd_hhmi,
eindtijd, to_char(eindtijd,'HH24:MI') eindtijd_hhmi from tst
where '22:00' between to_char(begintijd,'HH24:MI') and to_char(eindtijd,'HH24:MI')
;
Note that you use to_char with the date mask HH24:MI to get rid of the not relevant part of the date/time.
A probable better and more flexible way is to use INTERVALs.
with t2 as (
select
begintijd, begintijd - trunc(begintijd) begintijd_hhmi,
eindtijd, eindtijd - trunc(eindtijd) eindtijd_hhmi from tst)
select * from t2
where INTERVAL '22:00' HOUR TO MINUTE between begintijd_hhmi and eindtijd_hhmi
;
You use the difference of the timestamp and the truncated timestamp to calculate the interval (of hour and minutes). Note though, that if the timestamp can contain seconds or fractions of it, you may need to trim them out, e.g. with
NumToDsInterVal(60*extract(hour from begintijd)+extract(minute from begintijd),'MINUTE') begintijd_hhmi
Okay, so eventually, I was able to solve it. In my last update, the only lasting problem was that some variables weren't send to the next page. I wasn't able to find the root cause of the problem, so I did a workaround.
The only variable that was sent normally to the next page is P91_UITZENDING (the PK of Uitzending). Luckily, the other variables I needed (begintijd, eindtijd and datum) are attributes of Uitzending so I was able to derive them with statements like this in the source of the corresponding page item:
SELECT to_char(begintijd,'HH24:MI')
-- replace with eindtijd for eindtijd, and for date: to_char(datum,'DD-MON-YYYY')
FROM Uitzending
WHERE id = :P91_UITZENDING
And the final SQL query for the select box:
SELECT voornaam || ' ' || achternaam AS display_value, id AS return_value
FROM Gebruiker
WHERE -- Other statements
AND id IN (SELECT gebruikerid
FROM Beschikbaarheid
WHERE (dag = to_char(to_date(:P91_DATUM,'DD-MON-YYYY'),'fmDay','NLS_DATE_LANGUAGE=Dutch'))
AND (
to_date('01-01-2000' || :P91_BEGINTIJD,'DD-MM-YYYY HH24:MI')
BETWEEN
to_date('01-01-2000' || to_char(begintijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
AND
to_date('01-01-2000' || to_char(eindtijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
)
AND (
to_date('01-01-2000' || :P91_EINDTIJD,'DD-MM-YYYY HH24:MI')
BETWEEN
to_date('01-01-2000' || to_char(begintijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
AND
to_date('01-01-2000' || to_char(eindtijd,'HH24:MI'),'DD-MM-YYYY HH24:MI')
)
);
I still don't know why begintijd, eindtijd and datum weren't send the normal way, but at least it is working now.
Thank you all for your thinking and help!

Oracle - Format return of sysdate inside select

I did a select in oracle database to return the time that ticket is in a support group.
Sometimes, I have the scenario where we have the date of ticket joined the group, but I'm not out of time.
To workaround this problem, I put in my select a condition and worked with diff between the date of entry in the group and the sysdate.
The problem is the output that is being formatted as follows: +00 00:28:32.00000, and I need only the time in minutes.
Below, I added the whole query, I suppose that the problem is in this part:
CASE
WHEN PBTI_TEMPONOGRUPO IS NULL
THEN (SYSDATE-(SECS_TO_DATE(PBTI_DATAENTRADAGRUPO)))
END AS TEMPO_NO_GRUPO
How to format this output?
The query is:
SELECT PBTI_WORKORDER_ID AS ID_WO,
PBTI_IDREQUISICAO AS ID_REQ,
PBTI_GRUPOSUPORTEATUAL AS GRUPO_SUP_ATUAL,
PBTI_GRUPOSUPORTEANTERIOR AS GRUPO_SUP_ANTERIOR,
CASE
WHEN PBTI_DATASAIDAGRUPO IS NULL
THEN SYSDATE
WHEN PBTI_DATASAIDAGRUPO IS NOT NULL
THEN SECS_TO_DATE(PBTI_DATASAIDAGRUPO)
END AS DATA_SAIDA_GRUPO,
SECS_TO_DATE(PBTI_DATAENTRADAGRUPO) AS DATA_ENTRADA,
CASE
WHEN PBTI_TEMPONOGRUPO IS NULL
THEN (SYSDATE-(SECS_TO_DATE(PBTI_DATAENTRADAGRUPO)))
END AS TEMPO_NO_GRUPO
FROM PBTI_TABELA_INDICADORES
WHERE PBTI_WORKORDER_ID = 'WO0000000142585';
CASE
WHEN PBTI_DATASAIDAGRUPO IS NULL
THEN SYSDATE
WHEN PBTI_DATASAIDAGRUPO IS NOT NULL
THEN SECS_TO_DATE(PBTI_DATASAIDAGRUPO)
END
So the output of the CASE expressions will be DATE data type. To get the output in your desired format, use TO_CHAR along with desired FORMAT MODEL to convert it into a string.
For example,
SQL> SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD') only_date FROM DUAL;
ONLY_DATE
----------
2015-10-20
SQL> SELECT TO_CHAR(SYSDATE, 'HH24:MI:SS') only_time FROM DUAL;
ONLY_TIME
---------
20:29:54

Comparision of the timestamp in procedure not working

I have written a following query in my procedure which is not inserting the records in the TEST table. The KPI definition table has the following record:
KPI_DEF_ID KPI_FREQUENCY KPI_FREQ_TIME_UNIT EVENT_ID
1000136 30 MINUTE 10028
1000137 50 MINUTE 10028
I have a application in which user want to get the records depending on the timestamp. So user can enter in the application to get the records for example older than 30 min and newer than 24 hour. And the timestamp is changable. The older than timestamp comes from the KPI DEFINITION table and which is stored in the column KPI_FREQUENCY and KPI_FREQUENCY_UNIT and it can be changabler. And the newer than timestamp is fixed and i stored it in varaible LAST_OLDER_VAL and LAST_OLDER_VAL_UNIT. I used the insert using select query to store the records in table but its not working.
create or replace PROCEDURE "EXT_TEST" AS
LAST_WF_ID Number := 0;
--LAST_UNIT NUMBER:=10;
--LAST_UNIT_VAL VARCHAR2(20);
LAST_OLDER_VAL NUMBER := 24;
LAST_OLDER_VAL_UNIT VARCHAR2(10) := 'HOUR';
CURSOR WF_WORKFLOW_CUR IS
Select KPI_DEF_ID,KPI_FREQUENCY,KPI_FREQ_TIME_UNIT,EVENT_ID,BUSINESS_CHECK_PERIOD_ID FROM RATOR_MONITORING_CONFIGURATION.KPI_DEFINITION where EVENT_ID=10028;
BEGIN
--DBMS_OUTPUT.PUT_LINE('LAST_UNIT - ' || LAST_UNIT);
--DBMS_OUTPUT.PUT_LINE('LAST_UNIT_VAL - ' || LAST_UNIT_VAL);
-- removed, retrieve a new START_ID from source first, don't use the last id.
--SELECT LAST_TASK_ID INTO LAST_WF_ID FROM CAPTURING where DB_TABLE='TEMP_WF_WORKFLOW';
FOR WF_WORKFLOW_ROW IN WF_WORKFLOW_CUR
LOOP
--select MIN(ID) INTO LAST_WF_ID from WF_WORKFLOW#FONIC_RETAIL WF where WF.START_DATE > sysdate - numtodsinterval ( WF_WORKFLOW_ROW.KPI_FREQUENCY, WF_WORKFLOW_ROW.KPI_FREQ_TIME_UNIT );
Insert into TEST(ID,NAME,SUBSCRIPTION_ID,START_DATE,STATUS_ID,ACCOUNT_ID,END_DATE)
Select DISTINCT(WF.ID),WF.NAME,WF.SUBSCRIPTION_ID,WF.START_DATE,WF.STATUS_ID,WF.ACCOUNT_ID,WF.END_DATE
from WF_WORKFLOW#FONIC_RETAIL WF where WF.STATUS_ID = 0 and WF.NAME = 'SIGNUP_MOBILE_PRE_PAID'
and WF.START_DATE > SYSDATE - numtodsinterval ( LAST_OLDER_VAL, LAST_OLDER_VAL_UNIT
and WF.START_DATE < SYSDATE - numtodsinterval ( WF_WORKFLOW_ROW.KPI_FREQUENCY, WF_WORKFLOW_ROW.KPI_FREQ_TIME_UNIT ));
DBMS_OUTPUT.PUT_LINE('WF_WORKFLOW_ROW.KPI_FREQUENCY - ' || WF_WORKFLOW_ROW.KPI_FREQUENCY);
DBMS_OUTPUT.PUT_LINE('WF_WORKFLOW_ROW.KPI_FREQ_TIME_UNIT - ' || WF_WORKFLOW_ROW.KPI_FREQ_TIME_UNIT);
END LOOP;
END EXT_TEST;
You're currently looking for a start date that is older than 24 hours and newer than 30 minutes. Which is impossible, and not what you stated you needed, so that isn't what you mean really. Looks like you just have your < and > comparisons the wrong way around:
...
and WF.START_DATE > SYSDATE - numtodsinterval ( LAST_OLDER_VAL, LAST_OLDER_VAL_UNIT )
and WF.START_DATE < SYSDATE - numtodsinterval ( WF_WORKFLOW_ROW.KPI_FREQUENCY, WF_WORKFLOW_ROW.KPI_FREQ_TIME_UNIT );
Not directly relevant, but I'm not sure why you're using a loop for this, rather than a single insert ... select which joins WF_WORKFLOW_CUR and WF_WORKFLOW#FONIC_RETAIL. Or really why you'd use a stored procedure at all.

Update only date without modifying time

I have data in my database table as
last_updated_product
01/Jan/1899 6:25:01 AM
01/Jan/1899 6:25:02 AM
How can I update only the date part with sysdate without modifying the time part?
Expected outout
21/Aug/2013 6:25:01 AM
21/Aug/2013 6:25:02 AM
last_updated_product column data type is defined as date
Thanks
You need to use midnight on the current day, and add on the time part from the original value:
trunc(sysdate) + (last_updated_product - trunc(last_updated_product))
trunc() gives you the date with the time component set to 00:00:00, so date - trunc(date) gives you just the original time component, as a number (fraction of a day) as per the datetime arithmetic rules. That number can then be added on to midnight today.
Not sure if you're actually updating the table or just doing this in a query, but it's the same calculation either way.
You can either work out the time portion and add in the date you want, for instance:
update my_table
set last_updated_product =
to_date('21/Aug/2013', 'dd/Mon/yyyy')
-- difference between the start of the day and the time
+ (last_updated_product - trunc(last_updated_product))
The extra brackets are to ensure the query works according to the operator order of preference as you can't add a date to a date but you can add an interval. The brackets ensure that last_updated_product - trunc(last_updated_product) is evaluated before the addition takes place.
or convert it to a character, concatenate it to the date and then convert it back to a date.
update my_table
set last_updated_product =
to_date('21/Aug/2013' || to_char(last_updated_product, 'hh24:mi:ss')
, 'dd/Mon/yyyyhh24:mi:ss')
e.g.
create table my_table ( last_updated_product date );
Table created.
insert into my_table values (sysdate - 100);
1 row created.
update my_table
set last_updated_product =
to_date('21/Aug/2013', 'dd/Mon/yyyy')
+ (last_updated_product - trunc(last_updated_product))
;
1 row updated.
select * from my_table;
LAST_UPDATED_PRODUC
-------------------
2013/08/21 08:13:57
try
update <table>
set last_updated_product =
last_updated_product
- trunc(last_updated_product )
+ trunc(sysdate)
where <condition>
;