[MSSQL] Wyliczanie czasu trwania nachodzacych sie zajec

0

Mam sobie tabele z wpisami dotyczacymi pewnych spotkan.

table meetings ( 
  [id] int identity(1,1) primary key, 
  MeetingDate datetime, 
  Lasting datetime,  
  ...
)

MeetingDate - data i czas spotkania
Lasting - czas trwania spotkania

Spotkania moga sie nakladac, czyli jedno spotkanie moze zaczynac sie o jakiej porze i trwac np. 6h, a drugie zaczynac sie pol godziny pozniej i trwac 3h, itd.

Pytanie: W jaki sposob obliczyc jaki byl rzeczywisty czas trwania wszystkich spotkan. W powyzszym przypadku powinno wyjsc 6h (bo jedno jest zawarte w drugim).

Licze na jakies pomysly, bo ja na razie na zaden nie wpadlem i tez niewiele wygooglalem.

pozdrawiam
johny

0

A w sytuacji, w której masz powiedzmy jedno spotkanie 9-10 a drugie 11-12, to ma liczyć 2 godziny, czy 3 (od poczatku pierwszego, do końca ostatniego)?

0

2 godziny niestety...

Powiedzmy, ze jest jedna sala do zajec i jest w niej kilka rownoczesnych. I tu pytanie ile czasu ta 'sala' byla otwarta - w tym stylu liczenie.

Myslalem z tym liczeniem od poczatku pierwszego do ostatniego, ale znowu nie mam pomyslu jak znalezc dziury pomiedzy nimi.

Nawet niespecjalnie mam pomysl jak szukac czegos na google'u...

PS. To nie musi byc szybkie - rekordow branych pod uwage bedzie max rzedu 10000, wiec nawet jak bedzie wolne, to baza sobie da rade. Wazne, zeby liczylo poprawnie.

pozdrawiam
johny

0

Przychodzi mi do głowy taka opcja (wolna, ale raczej poprawna) - stworzenie dodatkowej tabeli (tymczasowej), a następnie wykonanie czegoś takiego:
Dla każdego rekordu z tabeli spotkań sprawdzamy, czy w tabeli tymczasowej jest element, który przecina się (całkowicie lub częściowo) z danym rekordem. Jeśli tak, to odpowiednio przesuwamy początek/koniec rekordu w tabeli tymczasowej, by znaleźć sumę (w sensie teoriomnogościowym) tych spotkań. Jeśli takich przecinających się rekordów w tabeli tymczasowej będzie więcej, to łączymy je w jeden.
Następnie z tabeli tymczasowej wyliczamy sumę czasu trwania każdego z tych rekordów.

Jeśli chodzi o implementację - trzebaby napisać procedurę dla bazy danych, w życiu tego nie robiłem, więc nie napiszę, jak to powinno dokładnie wyglądać.

Być może nie jest to idealne rozwiązanie (w sensie optymalizacji), jednak ja nie widzę lepszego.

0

Hmm... wlasnie wpadlem na cos podobnego i jestem w trakcie tworzenia :) Chociaz ja mam pomysl bez tabeli tymczasowej. Zobaczymy co wyjdzie :) Dzieki za poswiecony czas [soczek]

pozdrawiam
johny

...

No i napisalem :)

declare MeetingsCursor cursor read_only for 
select meetingdate, meetingdate+lasting from Meetings order by meetingdate, lasting

declare @meetingDate datetime
declare @endDate datetime
declare @startPoint datetime
declare @endPoint datetime
declare @sum datetime
set @sum = convert(datetime, '1900-01-01 00:00:00:000', 21)

open MeetingsCursor
fetch next from MeetingsCursor into @startPoint, @endPoint
fetch next from MeetingsCursor into @meetingDate, @endDate
WHILE (@@fetch_status <> -1)
begin
	if(@@fetch_status <> -2)
	begin
		if ((@startPoint<=@meetingDate) and (@endPoint >= @meetingDate)) --poczatek zawiera sie w przedziale
		begin
			if(@endDate > @endPoint) -- nie jest zawarte w liczonym okresie
			begin
				set @endPoint = @endDate
			end
		end
		else
		begin
			set @sum = @sum + @endPoint-@startPoint --dodajemy do wspolnej sumy 
			set @startPoint = @meetingDate          --i ustawiamy poczatek
			set @endPoint = @endDate                --i koniec na nastepny kawalek
		end
	end
	fetch next from MeetingsCursor into @meetingDate, @endDate
end
set @sum = @sum + @endPoint-@startPoint --dodajemy do wspolnej sumy koncowy zakres
close MeetingsCursor
deallocate MeetingsCursor
select @sum

Na 1000 rekordach trwa to 2s (Athlon XP 2,5GHz), wiec dla mnie bomba :)

Jakby ktos mial jakies uwagi (w szczegolnosci przyspieszajace) to chetnie wyslucham :)

pozdrawiam
johny

0

Hmm... Jeśli dobrze zrozumiałem, to wykorzystujesz sortowanie po czasie rozpoczęcia - sprytne :).

1 użytkowników online, w tym zalogowanych: 0, gości: 1