Selecting window of entries - sql

Consider the following (simplyfied) table:
ID NUMBER
PROD_NO VARCHAR2(10)
START_TIME DATE
What I want to do is selecting a 'window' of rows of size n around a given START_TIME.
Example:
ID PROD_NO START_TIME
...
42 1234567 2012-02-28 13:42:10
43 1234568 2012-02-28 13:47:53
44 1234569 2012-02-28 13:52:22
45 1234570 2012-02-28 13:59:01
46 1234571 2012-02-28 14:02:12
47 1234572 2012-02-28 14:05:19
...
Provided START_TIME = '2012-02-28 14:00:00' and window size n = 4 the resulting set of rows should be ID 44...47.
The entries cannot be assumed to be sorted by START_TIME. In case there are not enough entries available to match the specified window size, it may be cropped.
Since my SQL skills are pretty limited any help would be greatly appreciated.
Thanks in advance.

You can use analytic functions to help with this:
select WT.ID
from (select WT.ID
,max(
START_TIME)
over (order by START_TIME
rows between 2 preceding and 2 following)
as MAXST
,min(
START_TIME)
over (order by START_TIME
rows between 2 preceding and 2 following)
as MINST
from WT) WT
where MINST < to_date('2012-02-28 14:00:00', 'yyyy-mm-dd hh24:mi:ss')
and MAXST > to_date('2012-02-28 14:00:00', 'yyyy-mm-dd hh24:mi:ss')

This should work now:
SELECT *
FROM (SELECT id,
prod_no,
start_time,
ROWNUM rn,
datediff
FROM (SELECT id,
prod_no,
start_time,
start_time
- TO_DATE('01-JAN-2011 12:00:00',
'DD-MON-YYYY HH:MI:SS AM')
datediff
FROM table
WHERE start_time
- TO_DATE('01-JAN-2011 12:00:00',
'DD-MON-YYYY HH:MI:SS AM') > 0
ORDER BY datediff))
WHERE rn <= 2
UNION ALL
SELECT *
FROM (SELECT id,
prod_no,
start_time,
ROWNUM rn,
datediff
FROM (SELECT id,
prod_no,
start_time,
start_time
- TO_DATE('01-JAN-2011 12:00:00',
'DD-MON-YYYY HH:MI:SS AM')
datediff
FROM table
WHERE start_time
- TO_DATE('01-JAN-2011 12:00:00',
'DD-MON-YYYY HH:MI:SS AM') <= 0
ORDER BY datediff DESC))
WHERE rn <= 2

Related

Getting minimum value at a given time in SQL

I have the following SQL table:
start_time end_time value
2016-01-01 00:00:00 2016-01-01 08:59:59 1
2016-01-01 06:00:00 2016-01-01 14:59:59 2
2016-01-01 12:00:00 2016-01-01 17:59:59 1.5
2016-01-01 03:00:00 2016-01-01 17:59:59 3
I want to convert it into:
start_time end_time min_value
2016-01-01 00:00:00 2016-01-01 08:59:59 1
2016-01-01 09:00:00 2016-01-01 11:59:59 2
2016-01-01 12:00:00 2016-01-01 17:59:59 1.5
where min_value is the minimum value at a given point in time. Is it possible to do this in SQL?
Try below. I think it does exactly what you asked
As you can see - I added one more entry in your example to make it a little spicier :o)
WITH YourTable AS (
SELECT TIMESTAMP '2016-01-01 00:00:00' AS start_time, TIMESTAMP '2016-01-01 08:59:59' AS end_time, 1 AS value UNION ALL
SELECT TIMESTAMP '2016-01-01 06:00:00' AS start_time, TIMESTAMP '2016-01-01 14:59:59' AS end_time, 2 AS value UNION ALL
SELECT TIMESTAMP '2016-01-01 12:00:00' AS start_time, TIMESTAMP '2016-01-01 17:59:59' AS end_time, 1.5 AS value UNION ALL
SELECT TIMESTAMP '2016-01-01 03:00:00' AS start_time, TIMESTAMP '2016-01-01 17:59:59' AS end_time, 3 AS value UNION ALL
SELECT TIMESTAMP '2016-01-01 12:30:00' AS start_time, TIMESTAMP '2016-01-01 12:40:59' AS end_time, 1 AS value
),
Intervals AS (
SELECT iStart AS start_time, LEAD(iStart) OVER(ORDER BY iStart) AS end_time
FROM (
SELECT DISTINCT iStart FROM (
SELECT start_time AS iStart FROM YourTable UNION ALL
SELECT end_time AS iStart FROM YourTable )
)
),
Intervals_Mins AS (
SELECT b.start_time, b.end_time, MIN(value) AS min_value
FROM YourTable AS a
JOIN Intervals AS b
ON b.start_time BETWEEN a.start_time AND a.end_time
AND b.end_time BETWEEN a.start_time AND a.end_time
GROUP BY b.start_time, b.end_time
),
Intervals_Group AS (
SELECT start_time, end_time, min_value, IFNULL(SUM(flag) OVER(PARTITION BY CAST(min_value AS STRING) ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING), 0) AS time_group
FROM (
SELECT start_time, end_time, min_value, IF(end_time = LEAD(start_time) OVER(PARTITION BY CAST(min_value AS STRING) ORDER BY start_time), 0, 1) AS flag
FROM Intervals_Mins
)
)
SELECT MIN(start_time) AS start_time, MAX(end_time) AS end_time, min_value
FROM Intervals_Group
GROUP BY min_value, time_group
-- ORDER BY start_time
Hmmm . . . This seems hard. I think the following strategy will work:
Break the data into two parts, for start times and end times.
For each start time calculate the minimum value in effect at that time.
For each end time, calculate the minimum value in effect starting at that time.
Recombine using a gaps-and-islands approach
I'm just not 100% sure you can do this in BQ, because it involves non-equijoins. But . . .
with starts as (
select start_time as time,
(select min(t2.value)
from t t2
where t.start_time between t2.start_time and t2.end_time
) as value
from t
),
ends as (
select end_time as time,
(select min(t2.value)
from t t2
where t2.end_time > t.end_time and
t2.start_time <= t.end_time
) as value
from t
)
select value, min(time), max(time)
from (select time,
row_number() over (order by time) as seqnum,
row_number() over (partition by value order by time) as seqnum_v
from ((select s.* from starts) union all
(select e.* from ends)
) t
) t
group by value, (seqnum - seqnum_v);
I'm not sure that I understand how the expected output relates to the input, but if you just want to associate the minimum value with distinct (start_time, end_time) pairs, you can do e.g.:
#standardSQL
WITH T AS (
SELECT TIMESTAMP '2016-01-01 00:00:00' AS start_time,
TIMESTAMP '2016-01-01 08:59:59' AS end_time, 1 AS value UNION ALL
SELECT TIMESTAMP '2016-01-01 06:00:00',
TIMESTAMP '2016-01-01 14:59:59', 2 UNION ALL
SELECT TIMESTAMP '2016-01-01 12:00:00',
TIMESTAMP '2016-01-01 17:59:59', 1.5 UNION ALL
SELECT TIMESTAMP '2016-01-01 3:00:00',
TIMESTAMP '2016-01-01 17:59:59', 3
)
SELECT
start_time,
end_time,
MIN(value) AS min_value
FROM T
GROUP BY start_time, end_time;

SQL to calculate difference between 2 latest recent values by event_types

The events table looks like
event_type value timestamp
2 2 06-06-2016 14:00:00
2 7 06-06-2016 13:00:00
2 2 06-06-2016 12:00:00
3 3 06-06-2016 14:00:00
3 9 06-06-2016 13:00:00
4 9 06-06-2016 13:00:00
My goal is to filter event types that occur more than twice and subtract most two recent values and shows BY event_type.
The end result would be
event_type value
2 -5
3 -6
I was able to get filter events occurred more than twice and order by event_type based on timestamp desc.
The difficult part for me is to subtract most two recent values and shows BY event_type.
DB / SQL experts , please help
You can use a query like this:
SELECT event_type, diff
FROM (
SELECT event_type, value, "timestamp", rn,
value - LEAD(value) OVER (PARTITION BY event_type
ORDER BY "timestamp" DESC) AS diff
FROM (
SELECT event_type, value, "timestamp",
COUNT(*) OVER (PARTITION BY event_type) AS cnt,
ROW_NUMBER() OVER (PARTITION BY event_type ORDER BY "timestamp" DESC) AS rn
FROM mytable) AS t
WHERE cnt >=2 AND rn <= 2 ) AS s
WHERE rn = 1
The innermost subquery uses:
Window function COUNT with PARTITION BY clause, so as to calculate the population of each event_type slice.
Window function ROW_NUMBER so as to get the two latest records within each event_type slice.
The mid-level query uses LEAD window function, so as to calculate the difference between the first and the second records. The outermost query simply returns this difference.
Demo here
This example only for Oracle.
Test data:
with t(event_type,
value,
timestamp) as
(select 2, 2, to_timestamp('06-06-2016 14:00:00', 'mm-dd-yyyy hh24:mi:ss')
from dual
union all
select 2, 7, to_timestamp('06-06-2016 13:00:00', 'mm-dd-yyyy hh24:mi:ss')
from dual
union all
select 2, 2, to_timestamp('06-06-2016 12:00:00', 'mm-dd-yyyy hh24:mi:ss')
from dual
union all
select 3, 3, to_timestamp('06-06-2016 14:00:00', 'mm-dd-yyyy hh24:mi:ss')
from dual
union all
select 3, 9, to_timestamp('06-06-2016 13:00:00', 'mm-dd-yyyy hh24:mi:ss')
from dual
union all
select 4, 9, to_timestamp('06-06-2016 13:00:00', 'mm-dd-yyyy hh24:mi:ss')
from dual)
Query:
select event_type,
max(value) keep(dense_rank first order by rn) - max(value) keep(dense_rank last order by rn) as value
from (select event_type,
row_number() over(partition by event_type order by timestamp desc) rn,
value
from t) t
where rn in (1, 2)
group by event_type
having count (*) >= 2

Credit for sales report filing time

I have two date_time fields. The first is the date_time of the sale and the second is the date_time the sales report is filed.
In order for the salesperson to obtain credit, the sales report has to be filed by midnight on the date after the sale was made.
I'm currently calculating the difference, and know that anything over 24 hours could be out of a qualifying time period. Also, there are times when the sales report is filed prior to the date_time of the sale.
I searched through previous answers and couldn't find anything similar.
You need something like:
select to_char(report_time, 'mm/dd/yyyy hh24:mi:ss') report_time,
to_char(sales_time, 'mm/dd/yyyy hh24:mi:ss') sales_time,
round((report_time - sales_time) * 24, 6) diff_in_hours,
case when report_time < trunc(sales_time) + 2 then 'Y' else 'N' end decision
from sales
Function trunc() cuts hours, minutes and seconds from sales_time. For instance for date 01/15/2015 11:59:00 it returns 01/15/2015 00:00:00.
Next we add 2 days to this result. Report_date has to be lower then this value. So:
report_time < trunc(sales_time) + 2
Test with sample data:
with sales as (select
to_date('01/15/2015 11:59:00', 'mm/dd/yyyy hh24:mi:ss') report_time,
to_date('01/15/2015 11:45:00', 'mm/dd/yyyy hh24:mi:ss') sales_time from dual
union all select
to_date('01/16/2015 23:59:00', 'mm/dd/yyyy hh24:mi:ss'),
to_date('01/15/2015 12:45:00', 'mm/dd/yyyy hh24:mi:ss') from dual
union all select
to_date('01/17/2015 00:00:01', 'mm/dd/yyyy hh24:mi:ss'),
to_date('01/15/2015 23:59:00', 'mm/dd/yyyy hh24:mi:ss') from dual)
select to_char(report_time, 'mm/dd/yyyy hh24:mi:ss') report_time,
to_char(sales_time, 'mm/dd/yyyy hh24:mi:ss') sales_time,
round((report_time - sales_time) * 24, 6) diff_in_hours,
case when report_time < trunc(sales_time) + 2 then 'Y' else 'N' end decision
from sales
Output:
REPORT_TIME SALES_TIME DIFF_IN_HOURS DECISION
------------------- ------------------- ------------- --------
01/15/2015 11:59:00 01/15/2015 11:45:00 0,233333 Y
01/16/2015 23:59:00 01/15/2015 12:45:00 35,233333 Y
01/17/2015 00:00:01 01/15/2015 23:59:00 24,016944 N

Count records per hour within a time span

I have a table with a userID, a startDate and an endDate.
I would like to count hour by hour the number of userID concerned.
For example, the user '4242' with startDate = '21/05/2014 01:15:00' and with endDate = '21/05/2014 05:22:00' should be counted once from 01 to 02, once from 02 to 03, once from 03 to 04, ...
It would give a result like that:
DATE AND TIME COUNT
-------------------------------------
20140930 18-19 198
20140930 19-20 220
20140930 20-21 236
20140930 21-22 257
20140930 22-23 257
20140930 23-00 257
20141001 00-01 259
20141001 01-02 259
20141001 02-03 258
20141001 03-04 259
20141001 04-05 258
20141001 05-06 258
How would you do that ?
Well, I tried a lot of things. Here's my latest attempt. If the code is too messy, don't even bother reading it, just tell me how you would handle this problem ;) Thanks !
WITH timespan AS (
SELECT lpad(rownum - 1,2,'00') ||'-'|| lpad(mod(rownum,24),2,'00') AS hours
FROM dual
connect BY level <= 24
),
UserID_min_max AS (
SELECT USERS.UserID,
min(USERS.date_startUT) AS min_date,
max(USERS.date_end) AS max_date,
code_etat
FROM USERS
WHERE (
(USERS.date_startUT >= to_date('01/10/2014 00:00:00','dd/MM/YYYY HH24:mi:ss')
AND USERS.date_end <= to_date('08/10/2014 23:59:00','dd/MM/YYYY HH24:mi:ss'))
OR ( USERS.date_startUT <= to_date('01/10/2014 00:00:00','dd/MM/YYYY HH24:mi:ss')
AND USERS.date_end >= to_date('01/10/2014 00:00:00','dd/MM/YYYY HH24:mi:ss')
AND USERS.date_end <= to_date('08/10/2014 23:59:00','dd/MM/YYYY HH24:mi:ss'))
OR (USERS.date_startUT BETWEEN to_date('01/10/2014 00:00:00','dd/MM/YYYY HH24:mi:ss') AND to_date('08/10/2014 23:59:00','dd/MM/YYYY HH24:mi:ss')))
GROUP BY USERS.UserID, code_etat
),
hours_list AS (
SELECT UserID, min_date, max_date, code_etat
, to_char(min_date + row_number() over (partition BY UserID ORDER BY 1)-1,'yyyymmdd') AS days
, to_char(min_date,'yyyymmdd') AS date_start
, to_char(min_date, 'hh24') || '-' || lpad(to_number(to_char(min_date, 'hh24')) + 1, 2, '00') AS timespan_date_start
, to_char(max_date,'yyyymmdd') AS date_end
, to_char(max_date, 'hh24') || '-' || lpad(to_number(to_char(max_date, 'hh24')) + 1, 2, '00') AS timespan_date_end
FROM UserID_min_max cmm
connect BY level <= trunc(max_date) - trunc(min_date)+1
AND PRIOR UserID = UserID
AND prior sys_guid() IS NOT NULL
),
all_timespan_hours_list AS (
SELECT lj.*, t.*, lj.days ||' '|| t.hours AS days_hours
FROM hours_list lj
JOIN timespan t
ON lj.days || t.hours >= lj.date_start || lj.timespan_date_start
AND lj.days || t.hours <= lj.date_end || lj.timespan_date_end
)
SELECT DISTINCT days_hours, COUNT(*)
FROM (
SELECT *
FROM all_timespan_hours_list ttlj
WHERE CODE_ETAT IN ('SOH','SOL')
)
GROUP BY days_hours
ORDER BY days_hours;
Here's how I would do something similar:
with dt_tab as (select trunc(:p_start_date, 'hh') + (level - 1)/24 hr
from dual
connect by level <= (trunc(:p_end_date, 'hh') - trunc(:p_start_date, 'hh'))*24 + 1),
sample_data as (select 4242 usr, to_date('21/05/2015 01:15:00', 'dd/mm/yyyy hh24:mi:ss') start_date, to_date('21/05/2015 05:22:00', 'dd/mm/yyyy hh24:mi:ss') end_date from dual union all
select 4243 usr, to_date('20/05/2015 18:32:42', 'dd/mm/yyyy hh24:mi:ss') start_date, to_date('21/05/2015 01:36:56', 'dd/mm/yyyy hh24:mi:ss') end_date from dual union all
select 4244 usr, to_date('21/05/2015 07:00:00', 'dd/mm/yyyy hh24:mi:ss') start_date, null end_date from dual)
select to_char(dt.hr, 'dd/mm/yyyy hh24-')||to_char(dt.hr + 1/24, 'hh24') date_and_time,
count(sd.usr) cnt
from dt_tab dt
left outer join sample_data sd on (dt.hr < nvl(sd.end_date, :p_end_date) and dt.hr >= sd.start_date)
group by to_char(dt.hr, 'dd/mm/yyyy hh24-')||to_char(dt.hr + 1/24, 'hh24')
order by date_and_time;
:p_start_date := 20/05/2015 08:00:00
:p_end_date := 21/05/2015 08:00:00
DATE_AND_TIME CNT
---------------- ---
20/05/2015 08-09 0
20/05/2015 09-10 0
20/05/2015 10-11 0
20/05/2015 11-12 0
20/05/2015 12-13 0
20/05/2015 13-14 0
20/05/2015 14-15 0
20/05/2015 15-16 0
20/05/2015 16-17 0
20/05/2015 17-18 0
20/05/2015 18-19 0
20/05/2015 19-20 1
20/05/2015 20-21 1
20/05/2015 21-22 1
20/05/2015 22-23 1
20/05/2015 23-00 1
21/05/2015 00-01 1
21/05/2015 01-02 1
21/05/2015 02-03 1
21/05/2015 03-04 1
21/05/2015 04-05 1
21/05/2015 05-06 1
21/05/2015 06-07 0
21/05/2015 07-08 1
21/05/2015 08-09 0
(depending on how your time period start and end dates are configured, you might want to change from using bind variables - eg. use the min/max dates in your table, etc)
The above works when I run it in Toad. For something that works in SQL*Plus, or when you run it as a script (e.g. in Toad), the below should work:
variable p_start_date varchar2(20)
variable p_end_date varchar2(20)
exec :p_start_date := '20/05/2015 08:00:00';
exec :p_end_date := '21/05/2015 08:00:00';
with dt_tab as (select trunc(to_date(:p_start_date, 'dd/mm/yyyy hh24:mi:ss'), 'hh') + (level - 1)/24 hr
from dual
connect by level <= (trunc(to_date(:p_end_date, 'dd/mm/yyyy hh24:mi:ss'), 'hh') - trunc(to_date(:p_start_date, 'dd/mm/yyyy hh24:mi:ss'), 'hh'))*24 + 1),
sample_data as (select 4242 usr, to_date('21/05/2015 01:15:00', 'dd/mm/yyyy hh24:mi:ss') start_date, to_date('21/05/2015 05:22:00', 'dd/mm/yyyy hh24:mi:ss') end_date from dual union all
select 4243 usr, to_date('20/05/2015 18:32:42', 'dd/mm/yyyy hh24:mi:ss') start_date, to_date('21/05/2015 01:36:56', 'dd/mm/yyyy hh24:mi:ss') end_date from dual union all
select 4244 usr, to_date('21/05/2015 07:00:00', 'dd/mm/yyyy hh24:mi:ss') start_date, null end_date from dual)
select to_char(dt.hr, 'dd/mm/yyyy hh24-')||to_char(dt.hr + 1/24, 'hh24') date_and_time,
count(sd.usr) cnt
from dt_tab dt
left outer join sample_data sd on (dt.hr < nvl(sd.end_date, to_date(:p_end_date, 'dd/mm/yyyy hh24:mi:ss')) and dt.hr >= sd.start_date)
group by to_char(dt.hr, 'dd/mm/yyyy hh24-')||to_char(dt.hr + 1/24, 'hh24')
order by date_and_time;
Try to use the function TRUNC(date,[fmt]) like this:
select trunc(some_date, 'HH24')
from some_table
group by trunc(some_date, 'HH24');
Try this:
SELECT
DATE_FORMAT(your_datetime_column, '%Y%m%d %H') AS `hourly`,
COUNT(*) AS `count`
FROM your_table
GROUP BY DATE_FORMAT(your_datetime_column, '%Y%m%d %H')

Modifying SQL Query

Previously i wanted to find
1- Batch id's
2- Upload time
3- Count of requests infront of each batch
i wrote the following query and it worked perfectly
SELECT REQUEST_BATCH_ID,To_CHAR(B.UPDATE_STAMP , 'DD/MM/YYYY HH24'),COUNT(*)
FROM bpdata.bulk_prov_detail B
WHERE B.REQUEST_BATCH_ID
IN
(
SELECT REQUEST_BATCH_ID
FROM bpdata.bulk_prov_master A
where A.START_TIME > to_DATE ('12/16/2014 00', 'MM/DD/YYYY HH24')
)
GROUP BY To_CHAR(B.UPDATE_STAMP , 'DD/MM/YYYY HH24'),REQUEST_BATCH_ID
order by 1 desc,2 desc
and I get the data in following format
Batch_ID Day/Date Count(*)
257658 17/12/2014 11 5
257658 17/12/2014 12 4
257657 17/12/2014 12 4
257656 17/12/2014 12 2
But now I want to count the total number of count() and the largest number of count() and I am unable to devise a query for that. Your help and guidance would be appreciated in that regard
EDITED:
Example of Required Output
Batch_ID Day/Date Count(*)
257658 17/12/2014 11 5
257658 17/12/2014 12 4
257657 17/12/2014 12 4
257656 17/12/2014 12 2
Sum(Count(*)) Largest_request Time
15 5 17/12/2014 11
Sum(Count(*)) and Largest_request and time is what I need now
I haven't tested, but it should be something like:
SELECT SUM(x.total) AS grandtotal
FROM (
SELECT REQUEST_BATCH_ID,To_CHAR(B.UPDATE_STAMP , 'DD/MM/YYYY HH24'),COUNT(*) AS total
FROM bpdata.bulk_prov_detail B
WHERE B.REQUEST_BATCH_ID
IN
(
SELECT REQUEST_BATCH_ID
FROM bpdata.bulk_prov_master A
where A.START_TIME > to_DATE ('12/16/2014 00', 'MM/DD/YYYY HH24')
)
GROUP BY To_CHAR(B.UPDATE_STAMP , 'DD/MM/YYYY HH24'),REQUEST_BATCH_ID
) x
FOR Max Count:
SELECT *
FROM (
SELECT REQUEST_BATCH_ID,To_CHAR(B.UPDATE_STAMP , 'DD/MM/YYYY HH24'),COUNT(*) AS total
FROM bpdata.bulk_prov_detail B
WHERE B.REQUEST_BATCH_ID
IN
(
SELECT REQUEST_BATCH_ID
FROM bpdata.bulk_prov_master A
where A.START_TIME > to_DATE ('12/16/2014 00', 'MM/DD/YYYY HH24')
)
GROUP BY To_CHAR(B.UPDATE_STAMP , 'DD/MM/YYYY HH24'),REQUEST_BATCH_ID
) x ORDER BY x.total DESC LIMIT 0,1
To get exactly what you are asking for, you join the 2 queries. (also untested)
SELECT
(
SELECT SUM(x.total) AS grandtotal
FROM (
SELECT REQUEST_BATCH_ID,To_CHAR(B.UPDATE_STAMP , 'DD/MM/YYYY HH24'),COUNT(*) AS total
FROM bpdata.bulk_prov_detail B
WHERE B.REQUEST_BATCH_ID
IN
(
SELECT REQUEST_BATCH_ID
FROM bpdata.bulk_prov_master A
where A.START_TIME > to_DATE ('12/16/2014 00', 'MM/DD/YYYY HH24')
)
GROUP BY To_CHAR(B.UPDATE_STAMP , 'DD/MM/YYYY HH24'),REQUEST_BATCH_ID
) x
) y,
(
SELECT *
FROM (
SELECT To_CHAR(B.UPDATE_STAMP , 'DD/MM/YYYY HH24') AS daydate,COUNT(*) AS total
FROM bpdata.bulk_prov_detail B
WHERE B.REQUEST_BATCH_ID
IN
(
SELECT REQUEST_BATCH_ID
FROM bpdata.bulk_prov_master A
where A.START_TIME > to_DATE ('12/16/2014 00', 'MM/DD/YYYY HH24')
)
GROUP BY To_CHAR(B.UPDATE_STAMP , 'DD/MM/YYYY HH24'),REQUEST_BATCH_ID
) x ORDER BY x.total DESC LIMIT 0,1
) z
You can use Subquery Factoring WITH Clause to achieve the same
with batch_query as
(
SELECT REQUEST_BATCH_ID,
To_CHAR(B.UPDATE_STAMP, 'DD/MM/YYYY HH24') upd_stmp,
COUNT(*) cnt
FROM bpdata.bulk_prov_detail B
WHERE B.REQUEST_BATCH_ID IN
(SELECT REQUEST_BATCH_ID
FROM bpdata.bulk_prov_master A
where A.START_TIME >
to_DATE('12/16/2014 00', 'MM/DD/YYYY HH24'))
GROUP BY To_CHAR(B.UPDATE_STAMP, 'DD/MM/YYYY HH24'),
REQUEST_BATCH_ID)
,batch_agg_query as
(SELECT max(cnt) max_cnt,sum(cnt) sum_cnt from batch_query )
select sum_cnt,max_cnt,batch_query.upd_stmp
FROM batch_query,batch_agg_query
where batch_query.cnt=batch_agg_query.max_cnt