2011-03-06 15 views
8

que tienen un conjunto de intervalos de fechas que consiste en ambas fechas parcial y totalmente superpuestas, así:eliminar y reducir fecha de la superposición de rangos

UserID StartDate EndDate 
====== ========== ========== 
1  2011-01-01 2011-01-02 <- A 
1  2011-01-01 2011-01-10 <- A 
1  2011-01-08 2011-02-15 <- A 
1  2011-02-20 2011-03-10 <- B 
2  2011-01-01 2011-01-20 <- C 
2  2011-01-15 2011-01-25 <- C 

El uso de T-SQL, me gustaría crear un nuevo conjunto de datos , por usuario, con los datos que se solapan eliminadas, se extienden los rangos y la eliminación de datos redundantes cuando sea necesario, lo que resulta en algo como esto:

UserID StartDate EndDate 
====== ========== ========== 
1  2011-01-01 2011-02-15 ('A', three rows combined, extending the range) 
1  2011-02-20 2011-03-10 ('B', no change, no overlaps here) 
2  2011-01-01 2011-01-25 ('C', two rows combined) 

cursores están bien si es necesario, pero si puedo prescindir de ellos que sería aún mejor.

+0

qué versión de SQL Server, 2005+? – RichardTheKiwi

+0

Sí, SQL Server 2005+. –

Respuesta

12

Para SQL Server 2005 +

-- sample table with data 
declare @t table(UserID int, StartDate datetime, EndDate datetime) 
insert @t select 
1, '20110101', '20110102' union all select 
1, '20110101', '20110110' union all select 
1, '20110108', '20110215' union all select 
1, '20110220', '20110310' union all select 
2, '20110101', '20110120' union all select 
2, '20110115', '20110125' 

-- your query starts below 

select UserID, Min(NewStartDate) StartDate, MAX(enddate) EndDate 
from 
(
    select *, 
     NewStartDate = t.startdate+v.number, 
     NewStartDateGroup = 
      dateadd(d, 
        1- DENSE_RANK() over (partition by UserID order by t.startdate+v.number), 
        t.startdate+v.number) 
    from @t t 
    inner join master..spt_values v 
     on v.type='P' and v.number <= DATEDIFF(d, startdate, EndDate) 
) X 
group by UserID, NewStartDateGroup 
order by UserID, StartDate 

Notas:

  1. Reemplazar @t con su nombre de la tabla
+0

¡Cosas geniales! ¡Funciona de maravilla! Tendré que examinar el uso de ** DENSE_RANK() **, que era nuevo para mí. ¡Gracias! –

+0

Vale la pena mencionar que para los intervalos de fechas superiores al número de filas devuelto por 'master..spt_values' esto no funcionará. En este caso, puede cruzar esa tabla para obtener un tamaño de ventana mayor. –

+0

Algunos documentos DENSE_RANK(): https://docs.microsoft.com/en-us/sql/t-sql/functions/dense-rank-transact-sql – Westy92

Cuestiones relacionadas