2012-09-19 22 views
7

Tengo una tabla llamada Detalles de ausencia y quiero agrupar las fechas secuenciales. En este caso, son los datosSQL Server Consulta para agrupar fechas secuenciales

EID  AbsenceType AbsenceStartDate    AbsenceEndDate 
769  Holiday  2012-06-25 00:00:00.000   2012-06-25 23:59:59.000 
769  Holiday  2012-06-26 00:00:00.000   2012-06-26 23:59:59.000 
769  Holiday  2012-09-03 00:00:00.000   2012-09-03 23:59:59.000 
769  Holiday  2012-09-04 00:00:00.000   2012-09-04 23:59:59.000 
769  Holiday  2012-09-05 00:00:00.000   2012-09-05 23:59:59.000 
769  Holiday  2012-09-06 00:00:00.000   2012-09-06 23:59:59.000 
769  Holiday  2012-09-07 00:00:00.000   2012-09-07 23:59:59.000 

el resultado que estoy tratando de llegar es

EID  AbsenceType AbsenceStartDate   AbsenceEndDate 
769  Holiday  2012-06-25 00:00:00.000   2012-06-26 23:59:59.000 
769  Holiday  2012-09-03 00:00:00.000   2012-09-07 23:59:59.000 

Cualquier ayuda es muy apreciada.

+0

Olvidó eliminar la columna AbsenceType del encabezado o agregar valores para esta columna. – Vikdor

+0

@ Vikdor - Es cierto que olvidé eliminar la columna de la razón de ausencia. Gracias por eso. – user1682461

+0

@podiluska - No he comenzado a escribir ninguna consulta todavía. Solo buscando punteros. – user1682461

Respuesta

0

Si entendí correctamente su pregunta, quiere encontrar intervalos de tiempo continuos en sus registros.
El problema principal será identificar lo que realmente constituye intervalo de tiempo continuo:
Si usted está buscando en ausencia en el trabajo que cualquier secuencia de

date1.09:00 to date1.18:00 
date2.09:00 to date2.18:00 

donde date2 es un día hábil siguiente después date1 puede considerarse continuo.

En su caso, es relativamente fácil, pero no podrá hacerlo en una sola consulta. Al menos no puedo pensar en una forma de hacerlo ahora.

P.S. El algoritmo "Islands and Gaps" sugerido por "podiluska" le ayudará a escribirlo en una sola consulta/procedimiento almacenado.

1

lo haría de la siguiente manera:

  1. identificar la lista de secuencia de las fechas de ausencia.

    SELECT 
        ad1.EID, ad1.StartDate, ad2.EndDate 
    FROM 
        AbsenceDetails ad1 
        JOIN AbsenceDetails ad2 
        ON ad1.EID = ad2.EID 
    WHERE 
        DATEDIFF(ss, ad1.EndDate, ad2.StartDate) = 1 
    

    Los resultados serían los siguientes:

    769 2012-06-25 00:00:00.000 2012-06-26 23:59:59.000 
    769 2012-09-03 00:00:00.000 2012-09-04 23:59:59.000 
    769 2012-09-04 00:00:00.000 2012-09-05 23:59:59.000 
    769 2012-09-05 00:00:00.000 2012-09-06 23:59:59.000 
    769 2012-09-06 00:00:00.000 2012-09-07 23:59:59.000 
    
  2. iterar a través de la lista e identificar la duración de inicio y final de cada tramo. Esto se hace mejor en la capa de la aplicación.

4

He simplificado su escenario para aislar el problema principal. Vamos a supose esta tabla con huecos:

with ns as (
select 1 as n union 
select 2 as n union 
select 3 as n union 
select 8 as n union --gap 
select 9 as n) 
select * 
into #ns 
from ns; 

Ahora, el resultado que usted está esperando para es:

ini fi 
--- -- 
1 3 
8 9 

Para obtener este resultado Masajeo los datos de esta manera: primero se crea dos puntos de vista con arranque y los períodos de finalización y segundo, uniré ambas vistas para obtener el resultado final. Tenga en cuenta que me uno a la mesa con él mismo para localizar comienza y termina períodos:

with 
inis as          -- identifying start periods 
(
    select n1.n 
    from #ns n1 
    left outer join #ns n2 
     on n1.n = n2.n + 1 
    where n2.n is null 
    ), 
fis as          -- identifying ends periods 
( 
    select n1.n 
    from #ns n1 
    left outer join #ns n2 
     on n1.n = n2.n - 1 
    where n2.n is null 
    ) 
select inis.n as ini, min(fis.n) as fi -- joining starts and ends 
from inis 
inner join fis 
    on inis.n <= fis.n 
group by inis.n 
; 

puede transferir esta técnica a sus datos y tipos de datos. Si tiene algún problema para traducir la consulta, no dude en preguntar.

Check query and results.

4

Aquí está la solución que trabajó para mí.

SELECT EID, AbsenceType, MIN(AbsenceStartDate) AS AbsenceStartDate, MAX(AbsenceEndDate) AS AbsenceEndDate 
FROM (SELECT EID, AbsenceType, AbsenceStartDate, AbsenceEndDate, 
     DATEADD(dd, - ROW_NUMBER() OVER (PARTITION BY EID, AbsenceType ORDER BY EID,AbsenceStartDate), AbsenceStartDate) 
     FROM AbsenceDetails 
     GROUP BY EID,AbsenceType,AbsenceStartDate,AbsenceEndDate 
    ) a(EID, AbsenceType, AbsenceStartDate, AbsenceEndDate, Grp) 
GROUP BY EID, AbsenceType, Grp; 
+0

+1 Esta es una muy buena respuesta. La próxima vez recuerda formatear el código –

Cuestiones relacionadas