text: with get_func as (
  select sample_start_time,a.snap_id, schemaname AS schema_name, funcname AS func_name,round(calls) AS calls,
  round(total_time) AS total_time, round(self_time) AS self_time
  from pg_stat_user_functions_history a, pg_awr_snapshots_cust b 
  where a.snap_id = b.snap_id
  and a.snap_id between :begin_snap_id and :end_snap_id
  order by schemaname,funcname,a.snap_id
  ),
  get_lag_data as (
  select sample_start_time,schema_name,func_name,snap_id,calls,
  case WHEN (calls-lag(calls::numeric,1,0::numeric) OVER (partition by schema_name,func_name ORDER BY snap_id) ) = calls then null
  else (calls-lag(calls::numeric,1,0::numeric) OVER (partition by schema_name,func_name ORDER BY snap_id) ) END AS delta_calls,
  case WHEN (total_time-lag(total_time::numeric,1,0::numeric) OVER (partition by schema_name,func_name ORDER BY snap_id) ) = total_time then null
  else (total_time-lag(total_time::numeric,1,0::numeric) OVER (partition by schema_name,func_name ORDER BY snap_id) ) END as Delta_total_time,
  case WHEN (self_time-lag(self_time::numeric,1,0::numeric) OVER (partition by schema_name,func_name ORDER BY snap_id) ) = self_time then null
  else (self_time-lag(self_time::numeric,1,0::numeric) OVER (partition by schema_name,func_name ORDER BY snap_id) ) END as Delta_self_time
  from get_func
  where  snap_id between :begin_snap_id-1 and :end_snap_id
  )
  ,time_partitioned_data as (
  select schema_name,func_name,round((sum(Delta_total_time)/sum(delta_calls))::numeric,2) AS AVG_TOTAL_TIME,
  sum(delta_calls) AS calls,
  round((sum(Delta_self_time)/sum(delta_calls))::numeric) AS AVG_SELF_TIME
  from get_lag_data
  where Delta_total_time is not null
  and delta_calls is not null
  group by schema_name,func_name
  having sum(delta_calls)>0
  )
  select * from time_partitioned_data
  order by AVG_TOTAL_TIME desc
  limit 20;
  