2011-01-22 16 views
5

¿Qué es una forma de encontrar espacios en un conjunto de fechas?¿Cuál es una buena manera de encontrar espacios en un conjunto de fechas?

Por ejemplo, tengo estos tramos de fecha:

1/ 1/11 - 1/10/11 
1/13/11 - 1/15/11 
1/20/11 - 1/30/11 

entonces tengo una fecha de inicio y final del 07/01/11 y 1/14/11.

Quiero ser capaz de decir que entre el 1/10/11 y el 1/13/11 hay una brecha por lo que la fecha de inicio y de finalización no es posible. O quiero devolver solo los espacios de fechas hasta el primer espacio encontrado.

Si esto se puede hacer en el servidor SQL, sería bueno.

Estaba pensando en revisar cada fecha para saber si aterriza en un diespan ... si no, entonces hay un hueco en ese día.

Respuesta

2
  • Saltar a segundo bloque último código para: *I want to be able to tell that between 1/10/11 and 1/13/11 there is a gap so the start and end date is* no es posible.
  • Saltar a último bloque de código para: *I want to return only the datespans up to the first gap encountered.*

En primer lugar, aquí es una tabla virtual para discutir

create table spans (date1 datetime, date2 datetime); 
insert into spans select '20110101', '20110110'; 
insert into spans select '20110113', '20110115'; 
insert into spans select '20110120', '20110130'; 

Esta es una consulta que lista, de forma individual, todas las fechas en el calendario

declare @startdate datetime, @enddate datetime 
select @startdate = '20110107', @enddate = '20110114' 
select distinct a.date1+v.number 
from spans A 
inner join master..spt_values v 
    on v.type='P' and v.number between 0 and datediff(d, a.date1, a.date2) 
-- we don't care about spans that don't intersect with our range 
where A.date1 <= @enddate 
    and @startdate <= A.date2 

Armado con esta consulta, ahora podemos probar para ver si hay alguna ga ps, por contando los días en el calendario contra el número esperado de días

declare @startdate datetime, @enddate datetime 
select @startdate = '20110107', @enddate = '20110114' 

select case when count(distinct a.date1+v.number) 
    = datediff(d,@startdate, @enddate) + 1 
    then 'No gaps' else 'Gap' end 
from spans A 
inner join master..spt_values v 
    on v.type='P' and v.number between 0 and datediff(d, a.date1, a.date2) 
-- we don't care about spans that don't intersect with our range 
where A.date1 <= @enddate 
    and @startdate <= A.date2 
-- count only those dates within our range 
    and a.date1 + v.number between @startdate and @enddate 

Otra forma de hacer esto es simplemente construir el calendario de @Start a @end al frente y mira a ver si hay un lapso con esta fecha

declare @startdate datetime, @enddate datetime 
select @startdate = '20110107', @enddate = '20110114' 
-- startdate+v.number is a day on the calendar 
select @startdate + v.number 
from master..spt_values v 
where v.type='P' and v.number between 0 
    and datediff(d, @startdate, @enddate) 

-- run the part above this line alone to see the calendar 
-- the condition checks for dates that are not in any span (gap) 
    and not exists (
    select * 
    from spans 
    where @startdate + v.number between date1 and date2) 

la consulta devuelve todos fechas que están vacíos en el rango de fechas @Start - @end un TOP 1 se puede añadir a simplemente ver si hay lagunas

para devuelva todos los registros que están antes del espacio, use la consulta como una tabla derivada en una consulta más grande

declare @startdate datetime, @enddate datetime 
select @startdate = '20110107', @enddate = '20110114' 
select * 
from spans 
where date1 <= @enddate and @startdate <= date2 -- overlaps 
    and date2 < (-- before the gap 
    select top 1 @startdate + v.number 
    from master..spt_values v 
    where v.type='P' and v.number between 0 
     and datediff(d, @startdate, @enddate) 
     and not exists (
     select * 
     from spans 
     where @startdate + v.number between date1 and date2) 
    order by 1 ASC 
) 
1

Suponiendo MySQL, algo como esto funcionaría:

select @olddate := null; 

select start_date, end_date, datediff(end_date, @olddate) as diff, @olddate:=enddate 
from table 
order by start_date asc, end_date asc 
having diff > 1; 

Básicamente: almacenar en caché fecha_final de la fila anterior en la variable @olddate, y luego hacer un diff en ese valor "viejo" con el enddate currel. La cláusula having devolverá solo los registros donde la diferencia entre dos filas sea mayor que un día.

descargo de responsabilidad: No he probado esto, pero la construcción de consulta básica debería funcionar.

1

Quiero ser capaz de decir que entre el 1/10/11 y el 13/01/11 hay una brecha tan la fecha de inicio y fin no es posible.

Creo que usted está haciendo esta pregunta: ¿los datos en su tabla tienen un espacio vacío entre la fecha de inicio y la fecha de finalización?

Creé una tabla de una columna, date_span, e inserté los espacios de fecha en ella.

Puede identificar un espacio contando el número de días entre la fecha de inicio y la fecha de finalización, y comparando el número de filas en date_span para el mismo rango.

select 
    date '2011-01-14' - date '2011-01-07' + 1 as elapsed_days, 
    count(*) from date_span 
where cal_date between '2011-01-07' and '2011-01-14'; 

vuelve

elapsed_days count  
--   -- 
8   6 

ya que no son iguales, hay una brecha en la tabla "date_span" entre 2011-01-07 y 2011-01-14. Me detendré allí por ahora, porque realmente no estoy seguro de lo que estás tratando de hacer.

Cuestiones relacionadas