How to improve performance with ORACLE SQL cast and truncate - oracle
SELECT * FROM (
SELECT * FROM (
SELECT '1112468381_PRC1_INC',sysdate,TRUNC((p.F_CREACION-i.F_CREACION)*86400),TRUNC((i.F_CREACION-i.FECHA_PRESENTACION)*86400),TRUNC((sysdate-cast(from_tz(cast(p.F_CREACION as timestamp),'GMT') at time zone 'CET' as date))*86400),'','','','', '','','','','','','','','','', p.ID_PROCEDIMIENTO,p.SECUENCIA,p.USUARIO,p.GRUPO,p.TABLA,p.ACCION,p.TEXTO,p.C1,p.C2,p.C3, p.ORIGEN_ACCION,'','','','',i.ESTADO,i.SEVERIDAD,i.NDAI,i.TABLA_RAIZ,i.SEC_BOLETIN_RAIZ, i.OMEGA1,i.SERIE_EXTERNA,i.UNIDAD_RESPONSABLE,i.UNIDAD_CREADORA,i.ESTADO_RESPONSABILIDAD,i.COD_JALON,i.ID1,i.ID2,i.ID3,i.ID4, i.REPERCUSION,i.TIPO_INCOMUNICACION,i.ESTADO_SAF,i.ESTADO_ACTUACION,i.ESTADO_GESTION,i.NUM_ACTUACIONES,i.NUM_ACTUACIONES_IM,i.COD_RED,i.AREA,i.RED, i.TIPO_ELEMENTO,i.TIPO_SINTOMA,i.NOM_PROVINCIA,i.PROVINCIA,i.TEMP1,i.TEMP2,i.TEMP3,i.TEMP4,i.TEMP5,i.TEMP6, i.TEMP7,i.AUX1,i.AUX2,i.AUX3,cast(from_tz(cast(i.FECHA_PRESENTACION as timestamp),'GMT') at time zone 'CET' as date),cast(from_tz(cast(i.F_CREACION as timestamp),'GMT') at time zone 'CET' as date) as I_F_CREACION,i.FECHA_AFECTACION_SERVICIO,i.FECHA_FRANQUEO,i.CADENA_DELEGACION,i.ESTADO_BOL_RAIZ, '','','','','',
CASE
WHEN i.TIPO_ELEMENTO='Equipo' THEN (SELECT E.MODO||'â'||E.COD_CLAVE||'â'||E.CLASE||'â'||E.TECNOLOGIA||'â'||E.TIPO_ELEMENTO_GENERICO||'â'||E.MODELO||'â'|| E.CATEGORIA_EDIFICIO ||'â'|| E.CODIGO_UBICACION ||'â'|| E.DESC_CLAVE ||'â'|| E.DESC_PRIMARIA ||'â'|| E.DESC_SECUNDARIA FROM IGRI.EQUIPO E WHERE E.SECUENCIA=i.SECUENCIA)
WHEN i.TIPO_ELEMENTO='Sistemas de Transporte' THEN (SELECT S.MODO||'â'||S.COD_SISTEMA||'â'||S.CLASE||'â'||S.JERARQUIA||'â'||S.TIPO_ELEMENTO_GENERICO||'â'||'FREE6'||'â'||'FREE7'||'â'||'FREE8'||'â'||'FREE9'||'â'||'FREE10'||'â'||'FREE11' FROM IGRI.SISTEMA S WHERE S.SECUENCIA=i.SECUENCIA )
ELSE 'ââââââââââ' END AS INV
FROM IGRI.PROCEDIMIENTO p,IGRI.BOL_INC_DE_RED i
WHERE
i.TABLA = p.TABLA AND
i.SECUENCIA = p.SECUENCIA AND
p.ID_PROCEDIMIENTO > '1112468381'
UNION ALL
SELECT '1112468381_PRC2_INC',sysdate,TRUNC((p.F_CREACION-i.F_CREACION)*86400),TRUNC((i.F_CREACION-i.FECHA_PRESENTACION)*86400),TRUNC((sysdate-cast(from_tz(cast(p.F_CREACION as timestamp),'GMT') at time zone 'CET' as date))*86400),'','','','', '','','','','','','','','','', p.ID_PROCEDIMIENTO,p.SECUENCIA,p.USUARIO,p.GRUPO,p.TABLA,p.ACCION,p.TEXTO,p.C1,p.C2,p.C3, p.ORIGEN_ACCION,'','','','',i.ESTADO,i.SEVERIDAD,i.NDAI,i.TABLA_RAIZ,i.SEC_BOLETIN_RAIZ, i.OMEGA1,i.SERIE_EXTERNA,i.UNIDAD_RESPONSABLE,i.UNIDAD_CREADORA,i.ESTADO_RESPONSABILIDAD,i.COD_JALON,i.ID1,i.ID2,i.ID3,i.ID4, i.REPERCUSION,i.TIPO_INCOMUNICACION,i.ESTADO_SAF,i.ESTADO_ACTUACION,i.ESTADO_GESTION,i.NUM_ACTUACIONES,i.NUM_ACTUACIONES_IM,i.COD_RED,i.AREA,i.RED, i.TIPO_ELEMENTO,i.TIPO_SINTOMA,i.NOM_PROVINCIA,i.PROVINCIA,i.TEMP1,i.TEMP2,i.TEMP3,i.TEMP4,i.TEMP5,i.TEMP6, i.TEMP7,i.AUX1,i.AUX2,i.AUX3,cast(from_tz(cast(i.FECHA_PRESENTACION as timestamp),'GMT') at time zone 'CET' as date),cast(from_tz(cast(i.F_CREACION as timestamp),'GMT') at time zone 'CET' as date) as I_F_CREACION,i.FECHA_AFECTACION_SERVICIO,i.FECHA_FRANQUEO,i.CADENA_DELEGACION,i.ESTADO_BOL_RAIZ, '','','','','',
CASE
WHEN i.TIPO_ELEMENTO='Equipo' THEN (SELECT E.MODO||'â'||E.COD_CLAVE||'â'||E.CLASE||'â'||E.TECNOLOGIA||'â'||E.TIPO_ELEMENTO_GENERICO||'â'||E.MODELO||'â'|| E.CATEGORIA_EDIFICIO ||'â'|| E.CODIGO_UBICACION ||'â'|| E.DESC_CLAVE ||'â'|| E.DESC_PRIMARIA ||'â'|| E.DESC_SECUNDARIA FROM IGRI.EQUIPO E WHERE E.SECUENCIA=i.SECUENCIA)
WHEN i.TIPO_ELEMENTO='Sistemas de Transporte' THEN (SELECT S.MODO||'â'||S.COD_SISTEMA||'â'||S.CLASE||'â'||S.JERARQUIA||'â'||S.TIPO_ELEMENTO_GENERICO||'â'||'FREE6'||'â'||'FREE7'||'â'||'FREE8'||'â'||'FREE9'||'â'||'FREE10'||'â'||'FREE11' FROM IGRI.SISTEMA S WHERE S.SECUENCIA=i.SECUENCIA )
ELSE 'ââââââââââ' END AS INV
FROM IGRI.PROCEDIMIENTO_2 p,IGRI.BOL_INC_DE_RED i
WHERE
i.TABLA = p.TABLA AND
i.SECUENCIA = p.SECUENCIA AND
p.ID_PROCEDIMIENTO > '1112468381'
) ORDER BY ID_PROCEDIMIENTO
) WHERE ROWNUM <= '3000'
In the tests that I have been carrying out my conclusions are the following:
In the where it penalizes i.TABLA = p.TABLA AND if this takes away the time improves I do not know the reason.
When in the select there are no operations of change time zones the time improves.
It seems that transformations of the type:
cast(from_tz(cast(p.F_CREACION as timestamp),'GMT') at time zone 'CET' as date)
TRUNC((p.F_CREACION-i.F_CREACION)*86400)
penalize excessively
Related
Finding average / median time duration in a dataset
I am using BigQuery and doing a capstone project for a course which needs us to analyze the data for a fictional cycling company. Of the data that we're given, we're given the start and end time of the trips per month including date, hour, minute and second. I have the data in SQL with TIMESTAMP type for started_at and ended_at and TIME type for trip_duration I would like to find the average and median trip per month for the data through SQL. I was able to find the max and min trip, however I could not use simply AVG function to find the average trip duration. What would be the best way to find the average and median times for trips? I tried converting the duration into minutes by : SELECT ended_at, started_at, (ended_at-started_at)*1440, FROM `case-study-367714.case_study.yearly_data` This gave the following result : but this does not make sense as the first row is supposed to be 1 hr 26 minutes or 86 minutes, but it is showing 2064 minutes.
Consider the approach below: with sample_data as ( select timestamp("2022-07-14 21:31:00") as ended_at, timestamp("2022-07-14 20:05:00") as started_at union all select timestamp("2022-07-12 22:14:00") as ended_at, timestamp("2022-07-12 21:25:00") as started_at union all select timestamp("2022-05-28 23:31:00") as ended_at, timestamp("2022-05-28 22:38:00") as started_at union all select timestamp("2022-05-11 15:59:00") as ended_at, timestamp("2022-05-11 14:26:00") as started_at union all select timestamp("2022-08-19 17:31:00") as ended_at, timestamp("2022-08-19 16:43:00") as started_at union all select timestamp("2022-05-03 16:45:00") as ended_at, timestamp("2022-05-03 15:59:00") as started_at union all select timestamp("2022-08-04 21:59:00") as ended_at, timestamp("2022-08-04 21:22:00") as started_at union all select timestamp("2021-10-18 15:52:00") as ended_at, timestamp("2021-10-18 14:45:00") as started_at union all select timestamp("2022-08-20 17:06:00") as ended_at, timestamp("2022-08-20 16:28:00") as started_at ), cte as ( select *, concat(extract(year from ended_at),"-" ,extract(month from ended_at)) as month_date, timestamp_diff(ended_at,started_at,minute) as duration_minutes, from sample_data ) select month_date, duration_minutes, avg(duration_minutes) over (partition by month_date) as average_duration_per_month, percentile_cont(duration_minutes, 0.5) over () as median from cte Output:
Thank you Ricco. I used a bit different code than what you had posted and was able to get the answer that I wanted for average trip duration, however the median is still giving me issues. I used : WITH dataset AS ( SELECT started_at, ended_at, member_casual, timestamp_diff(ended_at, started_at, MINUTE) as Minute_Trip_Duration, EXTRACT(MONTH FROM started_at) AS month, FROM case-study-367714.case_study.yearly_data ) select month, member_casual, avg(Minute_Trip_Duration) AS average_trip_duration, from dataset GROUP BY month,member_casual Using this code I was able to get the following data. I was able to get average data for each month by whether the rider is a member or a casual rider: enter image description here The only issue is that if I enter the median code to it like below, I get an error message saying "SELECT list expression references column Minute_Trip_Duration which is neither grouped nor aggregated" WITH dataset AS ( SELECT started_at, ended_at, member_casual, timestamp_diff(ended_at, started_at, MINUTE) as Minute_Trip_Duration, EXTRACT(MONTH FROM started_at) AS month, FROM case-study-367714.case_study.yearly_data ) select month, member_casual, avg(Minute_Trip_Duration) AS average_trip_duration, percentile_cont(Minute_Trip_Duration,0.5) OVER () AS Median_Trip_Duration from dataset GROUP BY month,member_casual
Oracle timestamp and Interval
I have a requirement to get records from a table that are systimestamp > LAST_UPDATE_TS + 5 minutes interval Could you please help with query? ORACLE DB - 11G Version. I have tried this as below but not working as expected. SYSTIMESTAMP : 11-MAR-20 06.06.00.070695 AM -05:00 LAST_UPDATE_TS : 11-MAR-20 06.05.50.781167 AM After applying this condition, systimestamp > LAST_UPDATE_TS + INTERVAL '5' MINUTE, I expect no data should return, but still i get rows that doesn't satisfy condition.
You are comparing SYSTIMESTAMP which is a TIMESTAMP WITH TIME ZONE data type to a TIMESTAMP(6) data type; this requires a conversion to a time zone. If you use: SELECT SESSIONTIMEZONE FROM DUAL; The you can see the time zone your session is using. On db<>fiddle, the default is UTC (+00:00) and running: SELECT DUMMY AS query1 FROM DUAL WHERE TIMESTAMP '2020-03-11 06:06:00.070695 -05:00' > TIMESTAMP '2020-03-11 06:05:50.781167' + INTERVAL '5' MINUTE Outputs: | QUERY1 | | :----- | | X | Since 2020-03-11 06:06:00.070695 -05:00 is greater than 2020-03-11 06:10:50.781167 +00:00. If you change the session time zone: ALTER SESSION SET TIME_ZONE = '-05:00'; and run the same query again (a different column alias was used to prevent caching): SELECT DUMMY AS query2 FROM DUAL WHERE TIMESTAMP '2020-03-11 06:06:00.070695 -05:00' > TIMESTAMP '2020-03-11 06:05:50.781167' + INTERVAL '5' MINUTE Then the output has zero rows: | QUERY2 | | :----- | If you want to manually set the timezone in the conversion then you can use the FROM_TZ function: SELECT DUMMY AS query3 FROM DUAL WHERE TIMESTAMP '2020-03-11 06:06:00.070695 -05:00' > FROM_TZ( TIMESTAMP '2020-03-11 06:05:50.781167', '-05:00' ) + INTERVAL '5' MINUTE Which, again, outputs zero rows: | QUERY3 | | :----- | db<>fiddle here
SYSTIMESTAMP returns a TIMESTAMP WITH TIME ZONE value which is compared with a TIMESTAMP value. Actually Oracle is doing this: SYSTIMESTAMP > FROM_TZ(LAST_UPDATE_TS + INTERVAL '5' MINUTE, SESSIONTIMEZONE) Comparison itself is performed on UTC times. SYSTIMESTAMP is returned in the time zone of database server's operating system. If this time zone is equal to your current SESSIONTIMEZONE then the condition works as expected. Either change your session time zone to the time zone of database server's operating system or try this one: LOCALTIMESTAMP > LAST_UPDATE_TS + INTERVAL '5' MINUTE which does not utilize time zones at all.
After checking few forums and other stackoverflow pages, I tried this and it seams to be working now. select * from table where cast(systimestamp as TIMESTAMP) > (lst_updt_ts + interval '3' minute);
Doing it the old way? systimestamp -5/(60*24) > LAST_UPDATE_TS
How to covert time to TIMEZONE in oracle
I would like to know how to convert current time to TIMEZONE in oracle I tried this and worked perfectly SELECT (select tzname from qct_timezone_config tzc where gmtoffset = (select usr_time_zone from qct_user_token where resource_id = 11385)) AS TIMEZONE, TO_CHAR(CAST(SYSTIMESTAMP AS TIMESTAMP WITH TIME ZONE) AT TIME ZONE (select tzname from qct_timezone_config tzc where gmtoffset = (select usr_time_zone from qct_user_token where resource_id = 11385)), 'DD-MON-RR HH:MI:SS.FF AM') AS USER_TIME FROM dual But what i want to know is what if the time '03-AUG-2017 11.00.00 AM' is sent from the other system (i want to convert this time to a specific TimeZone) and how to rewrite this query.
You already have everthing in you query, to convert a timestamp to a specific timezone you have to use "AT TIME ZONE" precising the timezone you want your timestamp to be converted: select systimestamp AT TIME ZONE 'America/Los_Angeles' "West Coast Time" from dual; I'm not sure what you want to accomplish and the timestamp you want to convert needs to include a timezone if you want to convert it to another timezone.
Can't get time zone information when using mod_plsql?
I have written a function to convert a date into a Unix time stamp. The function is written to work no matter what the current DST status is (e.g. EST or EDT). This is the function: function unix_time_from_date(in_date in date) return number as ut number := 0; tz varchar2(8) := ''; begin -- Get the local timezone from the passed in date -- Assuming the date supplied is for the local time zone select extract( timezone_abbr from cast(in_date as timestamp with local time zone) ) into tz from dual; -- Get the Unix timestamp select (new_time(in_date, tz, 'GMT') - to_date('01-JAN-1970', 'DD-MM-YYYY')) * ( 86400) into ut from dual; return ut; end unix_time_from_date; This function works great when I execute it from a client like JDeveloper. From what I gather, this is because the client is supplying time zone information to the first query. However, if I use the function from within a procedure that is called from a mod_plsql page, then I get the error ORA-01857: not a valid time zone. This error is being thrown from the new_time function because tz is set to 'UNK'. So, I implemented a work-around for this problem like so: function unix_time_from_date(in_date in date) return number as ut number := 0; tz varchar2(8) := ''; begin -- Get the local timezone from the passed in date -- Assuming the date supplied is for the local time zone select extract( timezone_abbr from cast(in_date as timestamp with local time zone) ) into tz from dual; if tz = 'UNK' then select extract( timezone_abbr from cast(sysdate as timestamp with local time zone) ) into tz from dual; end if; -- Get the Unix timestamp select (new_time(in_date, tz, 'GMT') - to_date('01-JAN-1970', 'DD-MM-YYYY')) * ( 86400) into ut from dual; return ut; end unix_time_from_date; Except, this still fails with tz being set to 'UNK'. Does anyone know what could be happening here? Why can't I get the local time zone abbreviation when the function is called from a Oracle Application Server process?
I guess this does not depends on the date parameter you are passing. It probably depends on the Operating system settings where the database server runs. In JDeveloper it is probably picking up from your Computers (OS) time zone settings. Try doing an ssh on the DB server and run the first two queries in your script (use the actual date in 'DD-MON-YY' format for first query). Both should be returning 'UNK'. The UNK (unknown) is likely because more than one timezone is returned.Examples: In the following examples, suppose that the current time zone is CST (US Central Time). SELECT NEW_TIME(SYSDATE, 'CST', 'GMT') FROM DUAL --returns the date in London. SELECT TO_CHAR(NEW_TIME(SYSDATE, 'CST', 'GMT'),'HH24:MI') FROM DUAL --returns the time, based on the 24-hour clock, in London. SELECT TO_CHAR(NEW_TIME(SYSDATE + (14 / 24), 'PST', 'PST'),'DD-MON-YY HH24:MI') FROM DUAL --returns the date and time in China. SELECT TO_CHAR(NEW_TIME(SYSDATE + (diff / 24), ‘GMT’, ‘GMT’),’DD-MON-YY HH24:MI’) FROM DUAL; --returns the date and time of your office.
Have you compared the NLS_DATE_FORMAT on your local machine and the server? You may find that a combination of differences in this, and the possibility that an impicit conversion is happening when the date is being passed in may be your problem here.
The function as written does not work when the session calling it does not have the time zone information set. Therefore, you need to explicitly specify the source time zone. The following function solves this problem (and corrects the return type): function unix_time_from_date ( in_date in date, in_src_tz in varchar2 default 'America/New_York' ) return integer as ut integer := 0; tz varchar2(8) := ''; tz_date timestamp with time zone; tz_stmt varchar2(255); begin -- Get the local time zone abbreviation from the passed in date tz_stmt := 'select systimestamp at time zone ''' || in_src_tz || ''' from dual'; execute immediate tz_stmt into tz_date; select extract(timezone_abbr from tz_date) into tz from dual; -- Get the Unix timestamp select (new_time(in_date, tz, 'GMT') - to_date('01-JAN-1970', 'DD-MM-YYYY')) * (86400) into ut from dual; return ut; end unix_time_from_date; Note the addition of a second parameter to the function. This parameter, in_src_tz, is used to indicate what time zone the in_date parameter is in. The value of in_src_tz should be one of the timezone listed in the tzname column of the v$timezone_names table. Also, you cannot simply select the value of the tzabbrev column in the v$timezone_names table due to time zone having multiple abbreviations. By using the extract, you will get the current abbreviation with DST factored in.
Oracle current_timestamp to seconds conversion
We are using Oracle database. In our table timestamp is stored as seconds since 1970, how can I convert the time stamp obtained through current_timestamp() function to seconds
This would do it: select round((cast(current_timestamp as date) - date '1970-01-01')*24*60*60) from dual Though I wouldn't use current_timestamp if I was only interested in seconds, I would use SYSDATE: select round((SYSDATE - date '1970-01-01')*24*60*60) from dual
Maybe not completely relevant. I had to resolve other way around problem (e.g. Oracle stores timestamp in V$RMAN_STATUS and V$RMAN_OUTPUT) and I had to convert that to date/timestamp. I was surprised, but the magic date is not 1970-01-01 there, but 1987-07-07. I looked at Oracle's history and the closest date I can think of is when they ported Oracle products to UNIX. Is this right? Here's my SQL SELECT /*+ rule */ to_char(min(stamp)/(24*60*60) + date '1987-07-07', 'DD-MON-YYYY HH24:MI:SS') start_tm , to_char(to_char(max(stamp)/(24*60*60) + date '1987-07-07', 'DD-MON HH24:MI:SS')) end_tm FROM V$RMAN_STATUS START WITH (RECID, STAMP) = (SELECT MAX(session_recid),MAX(session_stamp) FROM V$RMAN_OUTPUT) CONNECT BY PRIOR RECID = parent_recid ;
I needed to send timestamp to GrayLog via GELF from Oracle DB. I tried different versions and solutions but only one worked correctly. SQL: SELECT REPLACE((CAST(dat AS DATE) - TO_DATE('19700101', 'YYYYMMDD')) * 86400 + MOD(EXTRACT(SECOND FROM dat), 1), ',', '.') AS millis FROM (SELECT SYSTIMESTAMP AT TIME ZONE 'GMT' AS dat FROM dual) The result for Systmiestamp 2018/12/18 19:47:29,080988 +02:00 will be 1545155249.080988