Modifying SQL Query - sql

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

Related

Oracle SQL return 0 count if there are no orders between dates

select trunc(a.submitted_date,'HH') thehour
, count(1) count_in_hour
from your_order a
LEFT JOIN my_order b ON a.order_id = b.order_id
where a.state!='INCOMPLETE'
and b.substatus != 'DUMMY_IGNORE_INVENTORY'
and a.submitted_date>=trunc(to_date('20/01/2018 00:00:00','dd/mm/yyyy hh24:mi:ss'))
and a.submitted_date<=trunc(to_date('21/01/2018 00:00:00','dd/mm/yyyy hh24:mi:ss'))
group by trunc(a.submitted_date,'HH')
order by thehour asc;
I need to get count of orders between date, This returns me
21-JAN-18 00:00:00 | 3
21-JAN-18 01:00:00 | 4
21-JAN-18 02:00:00 | 5
21-JAN-18 03:00:00 | 6
21-JAN-18 04:00:00 | 7
21-JAN-18 08:00:00 | 7
21-JAN-18 09:00:00 | 4
21-JAN-18 10:00:00 | 9
I am not getting the results for 5,6 and 7 hours as there are no orders placed between this time but I need a query to return the count as 0 even if the orders are not placed in this time.
Like I need 24 rows as there are 24 hours between the dates
My Approach:
Taking your base query and expecting that it will give result in the below format
thehour count_in_hour
"21-JAN-18 00:00:00" 3
"21-JAN-18 01:00:00" 4
I am writing a sub query which generate 24 hrs for the same date and doing a right join with the above result. So even if you query is not getting data for all 24 hours you will get an entry from this sub query.
Sub query:
Try the below query.
select
to_char(to_date('21-JAN-18 00:00:00', 'dd/mm/yyyy HH24:MI:SS') + (level-1)/24, 'DD-MON-YY HH24:MI:SS') as col1
from dual
connect by level <=24;
Over All Query:
select
t2.col1,
decode(t1.count_in_hour,null,0,t1.count_in_hour) as count_in_hour
from
(
SELECT
trunc(
a.submitted_date,
'HH'
) thehour,
COUNT(1) count_in_hour
FROM
your_order a
LEFT JOIN my_order b ON a.order_id = b.order_id
WHERE
a.state != 'INCOMPLETE'
AND
b.substatus != 'DUMMY_IGNORE_INVENTORY'
AND
a.submitted_date >= trunc(TO_DATE('20/01/2018 00:00:00','dd/mm/yyyy hh24:mi:ss') )
AND
a.submitted_date <= trunc(TO_DATE('21/01/2018 00:00:00','dd/mm/yyyy hh24:mi:ss') )
GROUP BY
trunc(
a.submitted_date,
'HH'
)) t1 right join
(select
to_char(to_date('21-JAN-18 00:00:00', 'dd/mm/yyyy HH24:MI:SS') + (level-1)/24, 'DD-MON-YY HH24:MI:SS') as col1
from dual
connect by level <=24
) t2 on t1.thehour = to_date(t2.col1,'DD-MON-YY HH24:MI:SS') order by t2.col1;
You need to have a separate hour table, which is holding the 24 hours and need to join with that table to see hours with 0 counts.
CREATE TABLE OrderHours
(
OrderHour CHAR(2)
)
INSERT INTO OrderHours values('00'),('01')..,('24');
select h.OrderHour, count(*)
count_in_hour from OrderHour as h LEFT JOIN your_order a on h.OrderHour = trunc(a.submitted_date,'HH') LEFT JOIN my_order b ON a.order_id = b.order_id where a.order_id = b.order_id
and a.state!='INCOMPLETE' and b.substatus != 'DUMMY_IGNORE_INVENTORY'
and a.submitted_date>=trunc(to_date('20/01/2018 00:00:00','dd/mm/yyyy hh24:mi:ss'))
and a.submitted_date<=trunc(to_date('21/01/2018 00:00:00','dd/mm/yyyy hh24:mi:ss')) group by h.OrderHour order by thehour asc;

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

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')

Finding a 'run' of rows from an ordered result set

I'm trying to figure out a way of identifying a "run" of results (successive rows, in order) that meet some condition. Currently, I'm ordering a result set, and scanning by eye for particular patterns. Here's an example:
SELECT the_date, name
FROM orders
WHERE
the_date BETWEEN
to_date('2013-09-18',..) AND
to_date('2013-09-22', ..)
ORDER BY the_date
--------------------------------------
the_date | name
--------------------------------------
2013-09-18 00:00:01 | John
--------------------------------------
2013-09-19 00:00:01 | James
--------------------------------------
2013-09-20 00:00:01 | John
--------------------------------------
2013-09-20 00:00:02 | John
--------------------------------------
2013-09-20 00:00:03 | John
--------------------------------------
2013-09-20 00:00:04 | John
--------------------------------------
2013-09-21 16:00:01 | Jennifer
--------------------------------------
What I want to extract from this result set is all the rows attributed to John on 2013-09-20. Generally what I'm looking for is a run of results from the same name, in a row, >= 3. I'm using Oracle 11, but I'm interested to know if this can be achieved with strict SQL, or if some kind of analytical function must be used.
You need multiple nested window functions:
SELECT *
FROM
(
SELECT the_date, name, grp,
COUNT(*) OVER (PARTITION BY grp) AS cnt
FROM
(
SELECT the_date, name,
SUM(flag) OVER (ORDER BY the_date) AS grp
FROM
(
SELECT the_date, name,
CASE WHEN LAG(name) OVER (ORDER BY the_date) = name THEN 0 ELSE 1 END AS flag
FROM orders
WHERE
the_date BETWEEN
TO_DATE('2013-09-18',..) AND
TO_DATE('2013-09-22', ..)
) dt
) dt
) dt
WHERE cnt >= 3
ORDER BY the_date
Try this
WITH ORDERS
AS (SELECT
TO_DATE ( '2013-09-18 00:00:01',
'YYYY-MM-DD HH24:MI:SS' )
AS THE_DATE,
'John' AS NAME
FROM
DUAL
UNION ALL
SELECT
TO_DATE ( '2013-09-19 00:00:01',
'YYYY-MM-DD HH24:MI:SS' )
AS THE_DATE,
'James' AS NAME
FROM
DUAL
UNION ALL
SELECT
TO_DATE ( '2013-09-20 00:00:01',
'YYYY-MM-DD HH24:MI:SS' )
AS THE_DATE,
'John' AS NAME
FROM
DUAL
UNION ALL
SELECT
TO_DATE ( '2013-09-20 00:00:02',
'YYYY-MM-DD HH24:MI:SS' )
AS THE_DATE,
'John' AS NAME
FROM
DUAL
UNION ALL
SELECT
TO_DATE ( '2013-09-20 00:00:03',
'YYYY-MM-DD HH24:MI:SS' )
AS THE_DATE,
'John' AS NAME
FROM
DUAL
UNION ALL
SELECT
TO_DATE ( '2013-09-20 00:00:04',
'YYYY-MM-DD HH24:MI:SS' )
AS THE_DATE,
'John' AS NAME
FROM
DUAL
UNION ALL
SELECT
TO_DATE ( '2013-09-21 16:00:01',
'YYYY-MM-DD HH24:MI:SS' )
AS THE_DATE,
'Jennifer' AS NAME
FROM
DUAL)
SELECT
B.*
FROM
(SELECT
TRUNC ( THE_DATE ) THE_DATE,
NAME,
COUNT ( * )
FROM
ORDERS
WHERE
THE_DATE BETWEEN TRUNC ( TO_DATE ( '2013-09-18',
'YYYY-MM-DD' ) )
AND TRUNC ( TO_DATE ( '2013-09-22',
'YYYY-MM-DD' ) )
GROUP BY
TRUNC ( THE_DATE ),
NAME
HAVING
COUNT ( * ) >= 3) A,
ORDERS B
WHERE
A.NAME = B.NAME
AND TRUNC ( A.THE_DATE ) = TRUNC ( B.THE_DATE );
OUTPUT
9/20/2013 12:00:01 AM John
9/20/2013 12:00:02 AM John
9/20/2013 12:00:03 AM John
9/20/2013 12:00:04 AM John

Selecting window of entries

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