tags:

views:

419

answers:

7

Ok, got a tricky one here... If my data looks like this:

Table1

ID  Date_Created 
1   1/1/2009
2   1/3/2009
3   1/5/2009
4   1/10/2009
5   1/15/2009
6   1/16/2009

How do I get the records that are 2 days apart from each other? My end result set should be rows 1-3, and 5-6. Thanks!

A: 

Would this work?

select t1.id, t2.id 
  from table1 t1 
  join table1 t2 
    on t2.date_created - t1.date_created <= 2
scrible
almost, but not quite. Could still match if there's a record in between them. Though maybe that's what he wants?
Joel Coehoorn
What about days 4, 6, 8 days from now?
Jon
@Joel: How did you infer from the question that he wanted only consecutive records (by id)?
scrible
@Jon: The question is not "from now", but to find (pairs of) records that are apart by at most so many days, e.g. 2.
scrible
+1  A: 
SELECT l.*
FROM Table1 l
INNER JOIN Table1 r ON DATEDIFF(d, l.Date_Created, r.Date_Created) = 2
      AND r.Date_Created = (SELECT TOP 1 * FROM Table1 WHERE Date_Created > l.Date_Created ORDER BY Date_Create)
Joel Coehoorn
A: 

-- what does this give you?

select DISTINCT t1.id, t1.date_created, t2.id, t2.date_created from table1 t1, table1 t2 where datediff(dd,t1.date_created,t2.date_created) = 2 AND t1.id != t2.id ORDER BY t1.id;

abramN
A: 

I might suggest using programming code to do it. You want to collect groups of rows (separate groups). I don't think you can solve this using a single query (which would give you just one set of rows back).

Jon
This should work fine even if there are gaps in the dates.
Jon
Also don't let the '1/1/2009' date fool you into thinking that you don't need a > your_start_date (if a start date is even applicable).
cfeduke
A stored procedure which returns multiple result sets could probably accomplish this for you (I think multiple result sets are possible with sql server stored procedures).
Jon
A: 
select distinct t1.*
from Table1 t1
inner join Table1 t2 
    on abs(cast(t1.Date_Created - t2.Date_Created as float)) between 1 and 2
RedFilter
You should not have an abs() in there unless you want every pair of matching IDs to appear twice (e.g. both (1,2) and (2,1)
scrible
Wrong, it is required, to get the first record for example.
RedFilter
A: 

If you want to get the rows which are WITHIN 'N' days apart, you can try this:

select t1.date_created, t2.date_created 
from table1 t1, table1 t2 
where t1.id <> t2.id and 
      t2.date_created-t1.date_created between 0 and N;

for exmaple, as you said, if you want to get the rows which are WITHIN 2 days a part, you can use the below:

select t1.date_created,t2.date_created 
from table1 t1, table1.t2 
where t1.id <> t2.id and 
      t2.date_created-t1.date_created between 0 and 2;

I hope this helps....

Regards, Srikrishna.

Srikrishna
A: 

A cursor will be fastest, but here is a SELECT query that will do it. Note that for "up to N" days apart instead of 2 you'll have to replace the table Two with a table of integers from 0 to N-1 (and the efficiency will get worse).

I'll admit it's not entirely clear what you want, but I'm guess you want the ranges of rows that contain at least two rows in all and within which the successive rows are at most 2 days apart. If dates increase along with IDs, this should work.

with Two as (
  select 0 as offset union all select 1 
), r2(ID, Date_Created_o, dr) as (
  select
    ID, Date_Created+offset,
    Date_Created + offset - dense_rank() over (
      order by Date_Created+offset
    ) from r cross join Two
)
  select
    min(ID) as start, max(ID) as finish
  from r2
  group by dr
  having min(ID) < max(ID)
  order by dr;
Steve Kass