2013-05-16 14 views
5

Çalışılan sürekli zaman aralıklarında bir başlangıç ​​ve bitiş tarihi kombinasyonu almaya çalışıyorum. Açıklıklar, ilk satırın bitiş tarihinin, sonraki satırın bitiş tarihi ile aynı olduğu birden çok satırdan geçebilir. Hedeflenen sonuç, o aralık için çalışılan saatlerin toplamı ile sürekli bir tarih aralığı göstermektir.SQL: Birden çok satırda sürekli tarih aralıkları buluyor musunuz?

person startdate    enddate     hours 
------ ----------------------- ----------------------- ------ 
5163 2013-04-29 07:00:00.000 2013-04-29 11:00:00.000 4.00 
5163 2013-04-29 11:30:00.000 2013-04-29 15:30:00.000 4.00 
5163 2013-04-29 15:30:00.000 2013-04-29 19:06:00.000 3.60 
5851 2013-05-02 19:00:00.000 2013-05-02 23:00:00.000 4.00 
5851 2013-05-02 23:00:00.000 2013-05-03 00:00:00.000 1.00 
5851 2013-05-03 00:00:00.000 2013-05-03 00:31:00.000 0.52 

Yukarıdaki verilerden aşağıdakileri istiyorum. Her kişi ve yeni (kesintili) tarih aralığı için

person startdate    enddate     hours 
------ ----------------------- ----------------------- ------ 
5163 2013-04-29 07:00:00.000 2013-04-29 11:00:00.000 4.00 
5163 2013-04-29 11:30:00.000 2013-04-29 19:06:00.000 7.60 
5851 2013-05-02 19:00:00.000 2013-05-03 00:31:00.000 5.52 

sonraki satırın STARTDATE geçerli satırın bitiş tarihi karşılaştırın. Aynıysa, saatleri toplayın ve bitiş/başlangıç ​​tarihi eşitleninceye kadar satırları işlemeye devam edin.

Ortam, SQL Server 2008 R2'dir. Self_nine ile ilgili sorguları, row_number ve partition() işlevlerini kullanarak denedim, ancak başarılı bir çözüm elde edemedim. Teşekkürler!

düzenleme: İşte RichardTheKiwi'nin çözümü için veri akışı - Bir hafta boyunca yumruklar için ne kadar yineleme oluşturulduğunu görmek için bir kişi için koştum.

declare @startdate datetime; 
    set @startdate = '20130429'; 
declare @enddate datetime; 
    set @enddate = '20130506'; 

with tbl as (
select 
PERSONNUM, 
STARTDTM, 
ENDDTM, 
convert(decimal(10,2),1.0 * TIMEINSECONDS/3600) as timeinhours 
from vp_totals 
where paycodetype = 'p' 
and applydate >= @startdate and APPLYDATE < @enddate 
and (paycodename like '%regular%' 
    or paycodename like '%overtime%' 
    or PAYCODENAME like '%double time%') 
and (PAYCODENAME not like '%shift premium%') 
and PERSONNUM = 'loh-5851' 
) 

select * from tbl order by startdtm -- 27 rows 


PERSONNUM  STARTDTM   ENDDTM    timeinhours 
LOH-5851  2013-04-29 14:30:00 2013-04-29 18:30:00 4.0000 
LOH-5851  2013-04-29 19:00:00 2013-04-29 23:00:00 4.0000 
LOH-5851  2013-04-29 23:00:00 2013-04-30 00:00:00 1.0000 
LOH-5851  2013-04-30 00:00:00 2013-04-30 00:11:00 0.1800 
LOH-5851  2013-04-30 14:45:00 2013-04-30 18:45:00 4.0000 
LOH-5851  2013-04-30 19:15:00 2013-04-30 23:00:00 3.7500 
LOH-5851  2013-04-30 23:00:00 2013-04-30 23:15:00 0.2500 
LOH-5851  2013-04-30 23:15:00 2013-05-01 00:00:00 0.7500 
LOH-5851  2013-05-01 00:00:00 2013-05-01 00:11:00 0.1800 
LOH-5851  2013-05-01 14:30:00 2013-05-01 18:30:00 4.0000 
LOH-5851  2013-05-01 19:00:00 2013-05-01 23:00:00 4.0000 
LOH-5851  2013-05-01 23:00:00 2013-05-02 00:00:00 1.0000 
LOH-5851  2013-05-02 00:00:00 2013-05-02 00:22:00 0.3700 
LOH-5851  2013-05-02 14:30:00 2013-05-02 18:30:00 4.0000 
LOH-5851  2013-05-02 19:00:00 2013-05-02 23:00:00 4.0000 
LOH-5851  2013-05-02 23:00:00 2013-05-03 00:00:00 1.0000 
LOH-5851  2013-05-03 00:00:00 2013-05-03 00:31:00 0.5200 
LOH-5851  2013-05-03 14:45:00 2013-05-03 17:45:00 3.0000 
LOH-5851  2013-05-03 17:45:00 2013-05-03 18:45:00 1.0000 
LOH-5851  2013-05-03 19:15:00 2013-05-03 23:00:00 3.7500 
LOH-5851  2013-05-03 23:00:00 2013-05-03 23:15:00 0.2500 
LOH-5851  2013-05-03 23:15:00 2013-05-04 00:00:00 0.7500 
LOH-5851  2013-05-04 00:00:00 2013-05-04 00:15:00 0.2500 
LOH-5851  2013-05-04 14:00:00 2013-05-04 18:00:00 4.0000 
LOH-5851  2013-05-04 18:30:00 2013-05-04 22:30:00 4.0000 
LOH-5851  2013-05-04 22:30:00 2013-05-04 23:00:00 0.5000 
LOH-5851  2013-05-04 23:00:00 2013-05-04 23:30:00 0.5000 


,cte as (
    select personnum, startdtm, enddtm, timeinhours 
    from tbl 
    union all 
    select t.personnum, cte.startdtm, t.enddtm, cast(cte.timeinhours + t.timeinhours as decimal(10,2)) 
    from cte 
    join tbl t on cte.personnum = t.personnum and cte.enddtm = t.startdtm 
) 

select * from cte order by startdtm, timeinhours option (maxrecursion 32000) -- 52 rows 



personnum  startdtm   enddtm    timeinhours 
LOH-5851  2013-04-29 14:30:00 2013-04-29 18:30:00 4.0000 
LOH-5851  2013-04-29 19:00:00 2013-04-29 23:00:00 4.0000 
LOH-5851  2013-04-29 19:00:00 2013-04-30 00:00:00 5.0000 
LOH-5851  2013-04-29 19:00:00 2013-04-30 00:11:00 5.1800 
LOH-5851  2013-04-29 23:00:00 2013-04-30 00:00:00 1.0000 
LOH-5851  2013-04-29 23:00:00 2013-04-30 00:11:00 1.1800 
LOH-5851  2013-04-30 00:00:00 2013-04-30 00:11:00 0.1800 
LOH-5851  2013-04-30 14:45:00 2013-04-30 18:45:00 4.0000 
LOH-5851  2013-04-30 19:15:00 2013-04-30 23:00:00 3.7500 
LOH-5851  2013-04-30 19:15:00 2013-04-30 23:15:00 4.0000 
LOH-5851  2013-04-30 19:15:00 2013-05-01 00:00:00 4.7500 
LOH-5851  2013-04-30 19:15:00 2013-05-01 00:11:00 4.9300 
LOH-5851  2013-04-30 23:00:00 2013-04-30 23:15:00 0.2500 
LOH-5851  2013-04-30 23:00:00 2013-05-01 00:00:00 1.0000 
LOH-5851  2013-04-30 23:00:00 2013-05-01 00:11:00 1.1800 
LOH-5851  2013-04-30 23:15:00 2013-05-01 00:00:00 0.7500 
LOH-5851  2013-04-30 23:15:00 2013-05-01 00:11:00 0.9300 
LOH-5851  2013-05-01 00:00:00 2013-05-01 00:11:00 0.1800 
LOH-5851  2013-05-01 14:30:00 2013-05-01 18:30:00 4.0000 
LOH-5851  2013-05-01 19:00:00 2013-05-01 23:00:00 4.0000 
LOH-5851  2013-05-01 19:00:00 2013-05-02 00:00:00 5.0000 
LOH-5851  2013-05-01 19:00:00 2013-05-02 00:22:00 5.3700 
LOH-5851  2013-05-01 23:00:00 2013-05-02 00:00:00 1.0000 
LOH-5851  2013-05-01 23:00:00 2013-05-02 00:22:00 1.3700 
LOH-5851  2013-05-02 00:00:00 2013-05-02 00:22:00 0.3700 
LOH-5851  2013-05-02 14:30:00 2013-05-02 18:30:00 4.0000 
LOH-5851  2013-05-02 19:00:00 2013-05-02 23:00:00 4.0000 
LOH-5851  2013-05-02 19:00:00 2013-05-03 00:00:00 5.0000 
LOH-5851  2013-05-02 19:00:00 2013-05-03 00:31:00 5.5200 
LOH-5851  2013-05-02 23:00:00 2013-05-03 00:00:00 1.0000 
LOH-5851  2013-05-02 23:00:00 2013-05-03 00:31:00 1.5200 
LOH-5851  2013-05-03 00:00:00 2013-05-03 00:31:00 0.5200 
LOH-5851  2013-05-03 14:45:00 2013-05-03 17:45:00 3.0000 
LOH-5851  2013-05-03 14:45:00 2013-05-03 18:45:00 4.0000 
LOH-5851  2013-05-03 17:45:00 2013-05-03 18:45:00 1.0000 
LOH-5851  2013-05-03 19:15:00 2013-05-03 23:00:00 3.7500 
LOH-5851  2013-05-03 19:15:00 2013-05-03 23:15:00 4.0000 
LOH-5851  2013-05-03 19:15:00 2013-05-04 00:00:00 4.7500 
LOH-5851  2013-05-03 19:15:00 2013-05-04 00:15:00 5.0000 
LOH-5851  2013-05-03 23:00:00 2013-05-03 23:15:00 0.2500 
LOH-5851  2013-05-03 23:00:00 2013-05-04 00:00:00 1.0000 
LOH-5851  2013-05-03 23:00:00 2013-05-04 00:15:00 1.2500 
LOH-5851  2013-05-03 23:15:00 2013-05-04 00:00:00 0.7500 
LOH-5851  2013-05-03 23:15:00 2013-05-04 00:15:00 1.0000 
LOH-5851  2013-05-04 00:00:00 2013-05-04 00:15:00 0.2500 
LOH-5851  2013-05-04 14:00:00 2013-05-04 18:00:00 4.0000 
LOH-5851  2013-05-04 18:30:00 2013-05-04 22:30:00 4.0000 
LOH-5851  2013-05-04 18:30:00 2013-05-04 23:00:00 4.5000 
LOH-5851  2013-05-04 18:30:00 2013-05-04 23:30:00 5.0000 
LOH-5851  2013-05-04 22:30:00 2013-05-04 23:00:00 0.5000 
LOH-5851  2013-05-04 22:30:00 2013-05-04 23:30:00 1.0000 
LOH-5851  2013-05-04 23:00:00 2013-05-04 23:30:00 0.5000 



,cte2 as (
    select *, rn = row_number() over (partition by personnum, enddtm order by startdtm) 
    from cte 
) 

select * from cte2 order by startdtm, rn -- 52 rows 


personnum  startdtm   enddtm    timeinhours  rn 
LOH-5851  2013-04-29 14:30:00 2013-04-29 18:30:00 4.0000    1 
LOH-5851  2013-04-29 19:00:00 2013-04-29 23:00:00 4.0000    1 
LOH-5851  2013-04-29 19:00:00 2013-04-30 00:00:00 5.0000    1 
LOH-5851  2013-04-29 19:00:00 2013-04-30 00:11:00 5.1800    1 
LOH-5851  2013-04-29 23:00:00 2013-04-30 00:11:00 1.1800    2 
LOH-5851  2013-04-29 23:00:00 2013-04-30 00:00:00 1.0000    2 
LOH-5851  2013-04-30 00:00:00 2013-04-30 00:11:00 0.1800    3 
LOH-5851  2013-04-30 14:45:00 2013-04-30 18:45:00 4.0000    1 
LOH-5851  2013-04-30 19:15:00 2013-04-30 23:00:00 3.7500    1 
LOH-5851  2013-04-30 19:15:00 2013-04-30 23:15:00 4.0000    1 
LOH-5851  2013-04-30 19:15:00 2013-05-01 00:11:00 4.9300    1 
LOH-5851  2013-04-30 19:15:00 2013-05-01 00:00:00 4.7500    1 
LOH-5851  2013-04-30 23:00:00 2013-05-01 00:00:00 1.0000    2 
LOH-5851  2013-04-30 23:00:00 2013-05-01 00:11:00 1.1800    2 
LOH-5851  2013-04-30 23:00:00 2013-04-30 23:15:00 0.2500    2 
LOH-5851  2013-04-30 23:15:00 2013-05-01 00:11:00 0.9300    3 
LOH-5851  2013-04-30 23:15:00 2013-05-01 00:00:00 0.7500    3 
LOH-5851  2013-05-01 00:00:00 2013-05-01 00:11:00 0.1800    4 
LOH-5851  2013-05-01 14:30:00 2013-05-01 18:30:00 4.0000    1 
LOH-5851  2013-05-01 19:00:00 2013-05-01 23:00:00 4.0000    1 
LOH-5851  2013-05-01 19:00:00 2013-05-02 00:00:00 5.0000    1 
LOH-5851  2013-05-01 19:00:00 2013-05-02 00:22:00 5.3700    1 
LOH-5851  2013-05-01 23:00:00 2013-05-02 00:22:00 1.3700    2 
LOH-5851  2013-05-01 23:00:00 2013-05-02 00:00:00 1.0000    2 
LOH-5851  2013-05-02 00:00:00 2013-05-02 00:22:00 0.3700    3 
LOH-5851  2013-05-02 14:30:00 2013-05-02 18:30:00 4.0000    1 
LOH-5851  2013-05-02 19:00:00 2013-05-02 23:00:00 4.0000    1 
LOH-5851  2013-05-02 19:00:00 2013-05-03 00:00:00 5.0000    1 
LOH-5851  2013-05-02 19:00:00 2013-05-03 00:31:00 5.5200    1 
LOH-5851  2013-05-02 23:00:00 2013-05-03 00:31:00 1.5200    2 
LOH-5851  2013-05-02 23:00:00 2013-05-03 00:00:00 1.0000    2 
LOH-5851  2013-05-03 00:00:00 2013-05-03 00:31:00 0.5200    3 
LOH-5851  2013-05-03 14:45:00 2013-05-03 17:45:00 3.0000    1 
LOH-5851  2013-05-03 14:45:00 2013-05-03 18:45:00 4.0000    1 
LOH-5851  2013-05-03 17:45:00 2013-05-03 18:45:00 1.0000    2 
LOH-5851  2013-05-03 19:15:00 2013-05-03 23:00:00 3.7500    1 
LOH-5851  2013-05-03 19:15:00 2013-05-03 23:15:00 4.0000    1 
LOH-5851  2013-05-03 19:15:00 2013-05-04 00:00:00 4.7500    1 
LOH-5851  2013-05-03 19:15:00 2013-05-04 00:15:00 5.0000    1 
LOH-5851  2013-05-03 23:00:00 2013-05-04 00:15:00 1.2500    2 
LOH-5851  2013-05-03 23:00:00 2013-05-04 00:00:00 1.0000    2 
LOH-5851  2013-05-03 23:00:00 2013-05-03 23:15:00 0.2500    2 
LOH-5851  2013-05-03 23:15:00 2013-05-04 00:00:00 0.7500    3 
LOH-5851  2013-05-03 23:15:00 2013-05-04 00:15:00 1.0000    3 
LOH-5851  2013-05-04 00:00:00 2013-05-04 00:15:00 0.2500    4 
LOH-5851  2013-05-04 14:00:00 2013-05-04 18:00:00 4.0000    1 
LOH-5851  2013-05-04 18:30:00 2013-05-04 22:30:00 4.0000    1 
LOH-5851  2013-05-04 18:30:00 2013-05-04 23:00:00 4.5000    1 
LOH-5851  2013-05-04 18:30:00 2013-05-04 23:30:00 5.0000    1 
LOH-5851  2013-05-04 22:30:00 2013-05-04 23:30:00 1.0000    2 
LOH-5851  2013-05-04 22:30:00 2013-05-04 23:00:00 0.5000    2 
LOH-5851  2013-05-04 23:00:00 2013-05-04 23:30:00 0.5000    3 


select personnum, startdtm, max(enddtm) enddtm, max(timeinhours) timeinhours 
from cte2 
where rn=1 
group by personnum, startdtm 
order by personnum, startdtm 
option (maxrecursion 32000) -- 12 rows 


personnum  startdtm   enddtm    timeinhours 
LOH-5851  2013-04-29 14:30:00 2013-04-29 18:30:00 4.0000 
LOH-5851  2013-04-29 19:00:00 2013-04-30 00:11:00 5.1800 
LOH-5851  2013-04-30 14:45:00 2013-04-30 18:45:00 4.0000 
LOH-5851  2013-04-30 19:15:00 2013-05-01 00:11:00 4.9300 
LOH-5851  2013-05-01 14:30:00 2013-05-01 18:30:00 4.0000 
LOH-5851  2013-05-01 19:00:00 2013-05-02 00:22:00 5.3700 
LOH-5851  2013-05-02 14:30:00 2013-05-02 18:30:00 4.0000 
LOH-5851  2013-05-02 19:00:00 2013-05-03 00:31:00 5.5200 
LOH-5851  2013-05-03 14:45:00 2013-05-03 18:45:00 4.0000 
LOH-5851  2013-05-03 19:15:00 2013-05-04 00:15:00 5.0000 
LOH-5851  2013-05-04 14:00:00 2013-05-04 18:00:00 4.0000 
LOH-5851  2013-05-04 18:30:00 2013-05-04 23:30:00 5.0000 

sorgu verilerinin küçük miktarlarda için mükemmel çalışır, ancak bir ödeme döneminde (genellikle bir hafta) için beklenen işçi nüfus için çalıştırdığınızda, çirkin max özyinelemeli bağıntılar hata mesajı görüntülenir.

düzenleme düzenle: Richard's fix the recursion issue.

cevap

4

Örnek veri

create table tbl (person int, startdate datetime, enddate datetime, hours decimal(10,2)); 
insert tbl values 
(5163 ,'2013-04-29 07:00:00.000' ,'2013-04-29 11:00:00.000', 4.00), 
(5163 ,'2013-04-29 11:30:00.000' ,'2013-04-29 15:30:00.000', 4.00), 
(5163 ,'2013-04-29 15:30:00.000' ,'2013-04-29 19:06:00.000', 3.60), 
(5851 ,'2013-05-02 19:00:00.000' ,'2013-05-02 23:00:00.000', 4.00), 
(5851 ,'2013-05-02 23:00:00.000' ,'2013-05-03 00:00:00.000', 1.00), 
(5851 ,'2013-05-03 00:00:00.000' ,'2013-05-03 00:31:00.000', 0.52); 

sorgu

;with cte as (
    select person, startdate, enddate, hours 
    from tbl 
    union all 
    select t.person, cte.startdate, t.enddate, cast(cte.hours + t.hours as decimal(10,2)) 
    from cte 
    join tbl t on cte.person = t.person and cte.enddate = t.startdate 
), cte2 as (
    select *, rn = row_number() over (partition by person, enddate order by startdate) 
    from cte 
) 
select person, startdate, max(enddate) enddate, max(hours) hours 
from cte2 
where rn=1 
group by person, startdate 
order by person, startdate; 

Sonuçlar

person  startdate    enddate     hours 
----------- ----------------------- ----------------------- ------- 
5163  2013-04-29 07:00:00.000 2013-04-29 11:00:00.000 4.00 
5163  2013-04-29 11:30:00.000 2013-04-29 19:06:00.000 7.60 
5851  2013-05-02 19:00:00.000 2013-05-03 00:31:00.000 5.52 
+0

Merhaba Richard, bu çözüm için teşekkür ederim! Bunu yanıt olarak işaretlemek istiyorum .... Verilmiş olan örnek verilerle çalışırken, üretim verileri üzerinde çalışırken, "Açıklama sonlandırıldı. Maksimum yineleme 100, bildirimin tamamlanmasından önce tükendi." Hatta ipucu "option (maxrecursion 32000)" kullandıktan sonra bile hata aldı. Üretim verileri yaklaşık 600 satırdır ve sorgu için 1.500 satıra kadar beklerim. Özyineleme sorunu etrafında çalışan alternatif bir yöntem var mı? – user2391335

+0

Son tarihin nerede başladığını gösteren bir kayıt var. Bu, (şu anda) sonsuz özyönüllülüğe sebep olabilecek tek şey. Bunu cte.person = t.person ve cte.enddate = t.startdate ve t.enddate = t.startdate 't-t tt t ile kullanarak engelleyebilirsiniz. – RichardTheKiwi

+0

Tekrar teşekkürler, Richard! Önerilen değişiklik özyineleme problemini düzeltmek için görünüyor ve örnek insanımın çıktısı doğru görünüyor. – user2391335

İlgili konular