Finding gaps between dates in table
Is this following possible in sql...
Lets say I have a "sales" table with these fields
SalesMan, SaleDate, Amount.
and this data
John, 6/may/07,90
John, 4/may/07,330
John, 2/may/07,200
John, 9/apr/07,300
John, 5/apr/07,300
Dave, 9/jul/07,90
Dave, 8/jul/07,90
Dave, 4/jul/07,330
Dave, 2/jul/07,200
Dave, 4/jun/07,300
Dave, 2/jun/07,300
I want to ask the database "show me the third sale made by each sales man after any 2 week gap in sales"
Here's the same data again...
John, 6/may/07,90 --- I want this one
John, 4/may/07,330
John, 2/may/07,200
<2 week gap>
John, 9/apr/07,300
John, 5/apr/07,300
Dave, 9/jul/07,90
Dave, 8/jul/07,90 --- and this one
Dave, 4/jul/07,330
Dave, 2/jul/07,200
<2 week gap>
Dave, 4/jun/07,300
Dave, 2/jun/07,300
My actual problem is more complicated but this is it in its most basic form.
Any help is much appreciated.
That's easy enough using the LAG analytic funtion.
with testdata as (select 'John' name, to_date('6/may/07') sdate, 90 amount from dual
union all select 'John', to_date('4/may/07'), 330 from dual
union all select 'John', to_date('2/may/07'), 200 from dual
union all select 'John', to_date('9/apr/07'), 300 from dual
union all select 'John', to_date('5/apr/07'), 300 from dual
union all select 'Dave', to_date('9/jul/07'), 90 from dual
union all select 'Dave', to_date('8/jul/07'), 90 from dual
union all select 'Dave', to_date('4/jul/07'), 330 from dual
union all select 'Dave', to_date('2/jul/07'), 200 from dual
union all select 'Dave', to_date('4/jun/07'), 300 from dual
union all select 'Dave', to_date('2/jun/07'), 300 from dual
), sales_gaps AS (
select name, sdate, amount,
lag(sdate,2) over (partition by name order by sdate, amount) -
lag(sdate,3) over (partition by name order by sdate, amount) delta
from testdata
SELECT NAME, SDATE, AMOUNT FROM SALES_GAPS WHERE DELTA >= 14
NAME SDATE AMOUNT
Dave 08-JUL-2007 12:00:00 90
John 06-MAY-2007 12:00:00 90
2 rows selected
Similar Messages
-
SQL Lead & Lag to find gap between dates
i have a table with two columns event_start and event_end :
CREATE TABLE MYBATCHTAB
EVENT_START DATE NOT NULL,
EVENT_END DATE NOT NULL
and my data is :
Insert into MYBATCHTAB
(EVENT_START, EVENT_END)
Values
(TO_DATE('08/12/2013 22:45:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('08/12/2013 23:55:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into MYBATCHTAB
(EVENT_START, EVENT_END)
Values
(TO_DATE('08/12/2013 15:30:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('08/12/2013 17:00:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into MYBATCHTAB
(EVENT_START, EVENT_END)
Values
(TO_DATE('08/12/2013 16:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('08/12/2013 17:30:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into MYBATCHTAB
(EVENT_START, EVENT_END)
Values
(TO_DATE('08/12/2013 20:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('08/12/2013 22:00:00', 'MM/DD/YYYY HH24:MI:SS'));
COMMIT;
Event Start
Event End
08/12/2013 15:30:00
08/12/2013 17:00:00
08/12/2013 16:00:00
08/12/2013 17:30:00
08/12/2013 20:00:00'
08/12/2013 22:00:00
08/12/2013 22:45:00
08/12/2013 23:55:00
and i want to find the first whole start - end period in this example start : 15:30 - end 17:30 (merging record 1&2 )
but not the third one for example not 15.30 - 22:00 or not 15.30 23:55 because there are gaps between end dates.
how can i do this using lead&lag ?
I'm not sure if this is the best approachMaybe a baby-step solution
select event_start,event_end
from (select event_start,
case when overlap is not null
then case when lead(overlap,1) over (order by event_start) is not null
then lead(event_end,1) over (order by event_start)
when lag(overlap,1) over (order by event_start) is not null
then null
end
else event_end
end event_end
from (select event_start,event_end,
case when lead(event_start,1) over (order by event_start) <= event_end
or lag(event_end,1) over (order by event_start) >= event_start
then 'overlap'
end overlap
from mybatchtab
where event_end is not null
order by event_start
EVENT_START
EVENT_END
08/12/2013 15:30:00
08/12/2013 17:30:00
08/12/2013 20:00:00
08/12/2013 22:00:00
08/12/2013 22:45:00
08/12/2013 23:55:00
or when there can be more than two consecutive overlaps
select event_start,
event_end
from (select case when lag_overlap is null
then event_start
end event_start,
case when coalesce(lead_overlap,lag_overlap) is null
then event_end
when lag_overlap is null and lead_overlap is not null
then lead(event_end) over (order by event_start)
end event_end
from (select event_start,event_end,
case when event_start < lag(event_end) over (order by event_start)
then 'overlap'
end lag_overlap,
case when event_end > lead(event_start) over (order by event_start)
then 'overlap'
end lead_overlap
from mybatchtab
where lead_overlap is null
or lag_overlap is null
where event_end is not null
and event_end is not null
order by event_start
Regards
Etbin -
Find gap between two dates from table
Hello All,
I want to find gap between two dates ,if there is no gap between two dates then it should return min(eff_dt) and max(end_dt) value
suppose below data in my item table
item_id eff_dt end_dt
10 20-jun-2012 25-jun-2012
10 26-jun-2012 28-jun-2012 There is no gap between two rows for item 10 then it should return rows like
item_id eff_dt end_dt
10 20-jun-2012 28-jun-2012
item_id eff_dt end_dt
12 20-jun-2012 25-jun-2012
12 27-jun-2012 28-jun-2012 There is gap between two rows for item 12 then it should return like
item_id eff_dt end_dt
12 20-jun-2012 25-jun-2012
12 27-jun-2012 28-jun-2012
I hv tried using below query but it giv null value for last row
SELECT item_id, eff_dt, end_dt, end_dt + 1 AS newd,
LEAD (eff_dt) OVER (PARTITION BY ctry_code, co_code, item_id ORDER BY ctry_code,
co_code, item_id) AS LEAD,
(CASE
WHEN (end_dt + 1) =
LEAD (eff_dt) OVER (PARTITION BY ctry_code, co_code, item_id ORDER BY ctry_code,
co_code, item_id, eff_dt)
THEN '1'
ELSE '2'
END
) AS new_num
FROM item
WHERE TRIM (item_id) = '802'
ORDER BY ctry_code, co_code, item_id, eff_dtI m using oracle 10g.
please any help is appreciate.
Thanks.Use start of group method:
with sample_table as (
select 10 item_id,date '2012-6-20' start_dt,date '2012-6-25' end_dt from dual union all
select 10,date '2012-6-26',date '2012-6-26' from dual
select item_id,
min(start_dt) start_dt,
max(end_dt) end_dt
from (
select item_id,
start_dt,
end_dt,
sum(start_of_group) over(partition by item_id order by start_dt) grp
from (
select item_id,
start_dt,
end_dt,
case lag(end_dt) over(partition by item_id order by start_dt)
when start_dt - 1 then 0
else 1
end start_of_group
from sample_table
group by item_id,
grp
order by item_id,
grp
ITEM_ID START_DT END_DT
10 20-JUN-12 26-JUN-12
SQL> SY. -
How to find the deleted data in tables
guys,
how to find the deleted data in tables example: i want to see whether anyone deleted data in MB5B report tables like mbew, etc.,
regards,Hi,
MBEWH is actually the history table of MBEW. It will record all the changes. As I have told you earlier if you have deleted the record dirctly from the table then it will not come even in the table MBEWH
That means no changes have been made.
regards -
I need to know how i can find difference between date
like Joining date: 01-jan-2009 Today 10-jan-2010 result will be "1 year 10 days"
I need it in Oracle forms 6i. plz help me...Hi,
In oracle forms you can use
RESULT :=
TRUNC ((:date2 - :date1 + 1) / 365)
|| ' year and '
|| MOD (:date2 - :date1 + 1, 365)
|| ' days';
in sql you can use
SELECT TRUNC ((:date2 - :date1 + 1) / 365)
|| ' year and '
|| MOD (:date2 - :date1 + 1, 365)
|| ' days'
FROM DUAL; -
Find out missing dates in table
Hi,
I've a table that sould have a record for day with sales info, but for some reason there are missing dates, is there any way i could find out witch dates are missing.
Table Example:
sales_date | value
2010-01-01 | 20
2010-01-02 | 30
2010-01-04 | 40
The output of the query for the example above sould return only the missing date (2010-01-03).
Thanks in advanceHow about (I wouldn't use this if your concerned about speed!)...
WITH src_data
AS (SELECT TO_DATE('2010-01-01', 'YYYY-MM-DD') sales_date FROM DUAL
UNION ALL
SELECT TO_DATE('2010-01-02', 'YYYY-MM-DD') sales_date FROM DUAL
UNION ALL
SELECT TO_DATE('2010-01-04', 'YYYY-MM-DD') sales_date FROM DUAL),
date_table
AS (SELECT LEVEL, MAX(sales_date) - LEVEL + 1 my_date
FROM src_data
CONNECT BY LEVEL <=
(SELECT MAX(sales_date) - MIN(sales_date) + 1
FROM src_data)
GROUP BY LEVEL
ORDER BY my_date ASC)
SELECT *
FROM date_table
WHERE NOT EXISTS (SELECT 1
FROM src_data
WHERE sales_date = my_date)Cheers
Ben -
To find the greatest date from table
guys,
I currently use this query to find the difference between sysdate and the oldest date in the table
select (SYSDATE - cur_date) from comp_check
the problem is it fives multiple records as output.
i want to design a query that will give the difference between sysdate and the oldest date in the table(it should throw only one record as the result)
how do i do that.
thanks in advanceSQL> select sysdate-min(created) from all_users
SQL> /
SYSDATE-MIN(CREATED)
507,373866
SQL> Nicolas.
MIN usage for oldest. Correction after ennisb's remark, thanks.
Message was edited by:
N. Gasparotto -
Hi,
I needed to compute the gap time between employments for my database. The problem I am running into right now is I am computing unnecessary calculations. For example,
Employment table:
job start date end date
A 13-01-2000 17-09-2002
B 25-02-2003 23-07-2004
C 22-01-2005 15-09-2007
My query is as follows:
SELECT A.job as Job1, B.job as Job2, (B.Start_Date - A.End_Date) as Gap_Time
FROM Employment A, Employment B
WHERE A.Start_Date != B.Start_Date AND A.End_Date != B.End_Date AND A.End_Date < B.Start_Date;
The problem is, I should only be getting the gap times between jobs (A,B) and then (B,C), but my query also computes the gap time between A and C (there shouldn't be one though because C does not directly follow job A so that wouldn't be a gap time between jobs). I've tried to mess around with the different types of joins for the FROM part of the query but still haven't been able to figure this out. Thanks.Look at the Analytic Functions and specifically the key words LAG and LEAD.
There is a lot of good advice at http://asktom.oracle.com and some demos in Morgan's Library at www.psoug.org. -
I was recently asked to help create a query at my company to search for date gaps in employment status history. My table data looks similar to this
employee_id employment_status beg_date end_date
1 Active 1990-01-01 1991-01-01
1 Leave 1991-02-01 1993-06-03
1 Active 1993-06-04 1995-02-01
1 Fired 2000-06-01 2299-12-31
So the gap im looking for would be from 1995-02-01 and 2000-06-01
Unfortunately as well, I dont have admin access to the database in order to be able to create an index, or do any fancy PL/SQL, im pretty much limited to the most basic SQL possible.
Any help appreciated!If your database supports analytic functions, the following query should give what you want.
with sample_data as (
select 1 employee_id, 'Active' employment_status, date '1990-01-01' beg_date, date '1991-01-01' end_date from dual union all
select 1, 'Leave', date '1991-02-01', date '1993-06-03' from dual union all
select 1, 'Active', date '1993-06-04', date '1995-02-01' from dual union all
select 1, 'Fired', date '2000-06-01', date '2299-12-31' from dual
select employee_id,
employment_status as last_status,
end_date as gap_lower_bound,
next_date as gap_upper_bound,
next_status
from
select t.*,
lead(beg_date) over(partition by employee_id order by beg_date) next_date,
lead(employment_status) over(partition by employee_id order by beg_date) next_status
from sample_data t
where next_date > end_date + 1
EMPLOYEE_ID LAST_STATUS GAP_LOWER_BOUND GAP_UPPER_BOUND NEXT_STATUS
1 Active 01/01/1991 01/02/1991 Leave
1 Active 01/02/1995 01/06/2000 Fired
Note #1 : the WITH clause is just there to generate some test data "on-the-fly", you can remove it and use your real table in place of SAMPLE_DATA in the main query.
Note #2 : unless you made a typo, the gap 01/01/1991 to 01/02/1991 should also be retrieved.
BTW, for specific questions about SQL or PL/SQL please use the {forum:id=75} forum.
Edited by: odie_63 on 27 févr. 2011 17:16 -
User defined function to find difference between dates
format of dtActivityStartDate/dtActivityFinishDate: 2010-09-17 14:50:51.150
usdFuncTimeCalc (vcActivityName,dtActivityStartDate, dtActivityFinishDate) -- user defined function
i need to calculate time elapsed for that type of activity following are the rules:
(If Process Request is the activity)
Working Days: Monday through Saturday
Hours of Operation: 9AM – 5PM
only working hours of day need to the counted like for example if it is sep 15 11 Am is dtActivityStartDate & Sep 17 is dtActivityFinishDate is 10 Am. then time elapsed is 11am to 5pm on sep 15 , 9 to 5 on sep 16 & 9 to 10 on sep 17 so total should be
6+ 8 + 1 = 15 hours + minutes.
format of date time: 2010-09-17 14:50:51.150
vcActivityName = Process Request
Don't worry about process request...I hv modified the code to make it more generic inorder to suit any timings (customizable) from Monday - Saturday.
declare
-- ** b u s i n e s s _ h o u r s **
-- business_hours returns the number of work houts (9 am through 5 pm,
-- Monday through Saturday) between in_start_dt and in_end_dt.
-- If in_start_dt > in_end_dt, the results will be <= 0.
-- Holidays are not considered.
in_start_dt DATE := to_date('15-SEP-2010 11:00:00','DD-MON-RRRR HH24:MI:SS');
in_end_dt DATE := to_date('17-SEP-2010 10:00:00','DD-MON-RRRR HH24:MI:SS');
d NUMBER; -- Hours of either start_dt or end_dt after midnight
end_dt DATE := GREATEST(in_start_dt, in_end_dt); -- In case dates were in wrong order
return_val NUMBER; -- Total number of working hours
start_dt DATE := LEAST(in_start_dt, in_end_dt); -- In case dates were in wrong order
start_time number := 9;
end_time number := 17;
BEGIN
WITH all_days AS(
SELECT start_dt + LEVEL - 1 AS a_dt
FROM dual
CONNECT BY LEVEL <= 1 + TRUNC(end_dt) - TRUNC(start_dt))
--SELECT SUM(12)
SELECT SUM(end_time-start_time)
INTO return_val
FROM all_days
WHERE TO_CHAR(a_dt,'Dy','NLS_DATE_LANGUAGE = ''ENGLISH''') NOT IN ('Sun');
dbms_output.put_line('Return_Val_1 : '||return_val);
-- Adjust hours from start_dt, if necessary
IF TO_CHAR(start_dt, 'Dy', 'NLS_DATE_LANGUAGE = ''ENGLISH''') NOT IN ('Sun') THEN
-- Calculate nbr of hours passed from midnight
d := 24 * (start_dt - TRUNC(start_dt));
dbms_output.put_line('d:'||d);
IF d >= end_time THEN -- d has passed 5 PM (end_time)
-- Don't count start_dt if it has passed the closing hours
return_val := return_val - (end_time-start_time);
dbms_output.put_line('if-d:'||return_val);
ELSIF d > start_time and d < end_time THEN -- d has passed 9 AM but less than 5 PM
-- Don't count the part of start_dt which has passed the opening hours
return_val := return_val - (d - start_time);
dbms_output.put_line('else-d:'||return_val);
END IF;
END IF;
dbms_output.put_line('');
dbms_output.put_line('Return_Val_2 : '||return_val);
-- Adjust hours from end_dt, if necessary
IF TO_CHAR(end_dt, 'Dy', 'NLS_DATE_LANGUAGE = ''ENGLISH''') NOT IN ('Sun') THEN
d := 24 * (end_dt - TRUNC(end_dt));
dbms_output.put_line('d:'||d);
IF d <= 9 THEN -- d < 9 AM
-- Don't count end_dt itself
return_val := return_val - (end_time-start_time);
dbms_output.put_line('if-d:'||return_val);
ELSIF d > start_time and d < end_time THEN -- d > 5 PM
-- Don't count part of end_dt
return_val := return_val - (end_time - d);
dbms_output.put_line('else-d:'||return_val);
END IF;
END IF;
dbms_output.put_line('');
dbms_output.put_line('Return_Val_3 : '||return_val);
IF in_start_dt > in_end_dt THEN
return_val := -return_val;
END IF;
dbms_output.put_line('');
dbms_output.put_line('Return_Val_4 : '||return_val);
END;Plz note the following points of the code :
1) You'll need to convert it a function, I just made it a declare..begin..end; block.
2) I hv used the same timings for start & end as you hv mentioned.
3) The 2 variables "start_time" and "end_time" take the opening & closing business hours respectively in a 24 hour format.
4) You might want to remove the DBMS_OUTPUT ... stmts which I had added for debugging.
It was an interesting code block to analyze ... :-) -
How to find gaps in data?
Hi!
I have the following problem.
Data:
range_id actual_nr
AAA 001AAA
AAA 002AAA
AAA 003AAA
AAA 006AAA
AAA 007AAA
AAA 009AAA
BBB 001BBB
BBB 002BBB
etc.
I have to get report in the following form
from to nr_of_rows
001AAA 003AAA 3
006AAA 007AAA 2
009AAA 1
001BBB 002BBB 2
etc.
As you can see if there is a gap in sequence then I have to calculate how many rows were in sequence before the gap.
Can somebody give me some hints or even working statement?How's this?
WITH
Sample_Data
AS
SELECT 'AAA' range_id, '001AAA' actual_nr FROM Dual UNION ALL
SELECT 'AAA' range_id, '002AAA' actual_nr FROM Dual UNION ALL
SELECT 'AAA' range_id, '003AAA' actual_nr FROM Dual UNION ALL
SELECT 'AAA' range_id, '006AAA' actual_nr FROM Dual UNION ALL
SELECT 'AAA' range_id, '007AAA' actual_nr FROM Dual UNION ALL
SELECT 'AAA' range_id, '009AAA' actual_nr FROM Dual UNION ALL
SELECT 'BBB' range_id, '001BBB' actual_nr FROM Dual UNION ALL
SELECT 'BBB' range_id, '002BBB' actual_nr FROM Dual
SELECT
MIN(actual_nr_start) actual_nr_start,
actual_nr_finish,
MAX(Total)
FROM
SELECT
range_id,
MIN(actual_nr) actual_nr_start,
MAX(actual_nr) actual_nr_finish,
MAX(Level) Total
FROM
Sample_Data
CONNECT BY
range_id = PRIOR range_id
AND substr(actual_nr, 1, 3) = substr(PRIOR actual_nr, 1, 3) + 1
GROUP BY
range_id,
CONNECT_BY_ROOT actual_nr
GROUP BY
actual_nr_finish
ORDER BY
SubStr(actual_nr_start, -3),
actual_nr_start;Message was edited by:
Brian Tkatch 2
consolidated two levels. -
Where we find changes in data of table
if log the table , it records the changes made to the data in the
table , where it stores the data.
regards,
ChanduCheck the tables CDHDR, CDPOS
CDHDR - Change Document Header table
CDPOS - Change Document Item table
Regards. -
Query to find oldest man data from table
Emp tab:
f_name varchar2(30)
l_name varchar2(30)
dob date
sex varchar2(5)
I want to find the F_name of the oldest man born in year 1965 , who possess the "DA" in the f_name.How about this?
SELECT f_name
FROM (SELECT *
FROM emp
WHERE TRUNC(dob) = 1965
AND UPPER(f_name) LIKE '%DA%'
ORDER BY dob desc
WHERE ROWNUM = 1
not tested and assuming that there are no duplicate dates. Another option would be analytic functions.
C. -
Data Source Tables in SAP BW 3.5
Hello Experts,
I am working on scenario where I need some information regarding data source present in 3.5 version.
I have checked RSDT table but it contains data for data sources present in 7.0 version only.
Please provide list of tables used for data soource and other objects for SAP BW 3.5 version.
Thanks in Advance.
Regards,
Sachin MotgiHi Sachin,
Please find the below Data Source tables for BW 3.5
RSTRANFIELD: Mapping of Rule Parameters, Structure Fields
ROOSOURCE: Info about Data Sources and to see how a datasource is extracting the data
RSOLTPSOURCE: list of DataSources by source system
ROOSPRMS : To set the data packet size forData Source
RODELTAM : Record mode
RSDCUBET RSDODSOT RSDIPROIOBJT RSQISETT: for Texts
RSDCUBE: InfoCube
RSDODSO: DSO
RSQISET: INFOSET
RSDDSTAT: Statistics BW data for aggregate selection and query accounting
Hope it helps.
Regards,
Raghu -
what is the by default gap between colums in table in oracle
This "gap" is something that the client tool introduces (or fails to introduce) for readability. In SQL*Plus, that is controlled by the COLSEP parameter.
SQL> set colsep ' 'will put three spaces between columns.
SQL> set colsep '|'will put one vertical pipe between columns.
I believe the default in SQL*Plus is generally to use a single space character as the column separator.
Justin
Maybe you are looking for
-
Urgant problem for the updating problem HELP
Dear sir/miss,On 2008.12.01 one of our partner company consultant,setup an update(SAPKH50016 AND SAPKH50017) page on our production system without and test in the test system. Now our transaction code CV03N,CV02N,CV01N can not be used,jump out abap p
-
Do i need to install leopard first? I was planning to but snow leopard off of amazon.
-
LISTENING FOR BACKSPACE WITH A KEY LISTENER
I have a key listener and I want to know how I find out if backspace has been pressed. Thanks
-
how do I export the whole score of a piece, without using the "camera device" which doesn't seem to work... thanks!
-
KO01 Internal order number range Pru00E4fix+internal number
Dear all, we have one worldwide controlling area. We would like to set up as less as possible internal order types. As you know you can assign behind each internal oder type the number range. We would like to have a number range with the company-code