0

I am trying to compare two columns in an SQL table based on two dates. The table is set up so the each person in table A has a foreign key to another table B, each person can have multiple entries in table B. Each entry in table B contains a start date and end date and I am trying to grab each person that has an overlap in table B so the Start Date of one of the entries is before the End Date of any other entry.

So John Doe in table A has two entries in table B where the start day of Entry 1 is April 5th 2015 and end date of April 6th 2016 and the second entry is January 10th 2016 and ends January 10th 2017, so I would want to include this person in my result set.

However Jane Doe in table A as two entries in table B

Entry 1: SD April 10th 2014 End April 10th 2015
Entry 2: SD May 11th 2015 End May 11th 2016

So I would not like to I include Jane Doe in my result set.

I am thinking I need to use two nested for loop in the where part of the select statement flipping a variable back and forth depending on whether or not I want to include this person.

Something along the lines of

Select * from A 
where 
(reset variable
for b in
(select * from b.id = A.b_id); loop
    for btwo in 
    (select * from b.id = A.b_id); loop
    // set variable based on start / end date
    // if I want to include set var = 1 else 0
    end loop;
end loop;)
variable = 1;

2 Answers 2

1

You've tagged this question for two database systems - my answer pertains to Oracle.

There's no need to use a loop here as you can use the SQL analytic function LAG to handle this sort of problem.

The following will provide the results you're looking for:

SELECT DISTINCT T.NAME
  FROM (SELECT A.NAME,
               B.START_DATE,
               B.END_DATE,
               LAG(B.START_DATE) OVER (PARTITION BY A.NAME ORDER BY B.NAME, B.START_DATE) AS PREV_START,
               LAG(B.END_DATE) OVER (PARTITION BY A.NAME ORDER BY B.NAME, B.START_DATE) AS PREV_END
          FROM A
          INNER JOIN B
            ON B.NAME = A.NAME
          ORDER BY A.NAME) T
  WHERE (T.START_DATE BETWEEN T.PREV_START AND T.PREV_END) OR
        (T.END_DATE BETWEEN T.PREV_START AND T.PREV_END) OR
        (T.PREV_START BETWEEN T.START_DATE AND T.END_DATE) OR
        (T.PREV_END BETWEEN T.START_DATE AND T.END_DATE);

SQLFiddle here

Sign up to request clarification or add additional context in comments.

Comments

0

Here is my suggestion. To get the overlaps you can use:

select b.*
from tableb b
where exists (select 1
              from tableb b2
              where b.aid = b2.aid and
                    b.startdate < b2.enddate and b.enddate > b.startdate
             );

The logic is simple. Two time spans overlaps if the first begins before the second ends, and the first ends after the second begins.

To get the table a values:

with overlaps as (
      select b.*
      from tableb b
      where exists (select 1
                    from tableb b2
                    where b.aid = b2.aid and
                          b.startdate < b2.enddate and b.enddate > b.startdate
                   )
    )
select a.*
from tablea a
where a.aid in (select o.aid from overlaps o);

Note: depending on how you define "overlap" you might want <= and >= for the comparisons.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.