今それをテストしました:http://sqlfiddle.com/#!3/a4e7a/2
ユーザーテーブルを想定しています。パフォーマンス改善の余地はたくさんあります。たとえば、重複しない範囲を除外する where 句を追加します。関数を恐ろしい case ステートメントに置き換えると、おそらく高速になります。
難しいのは、2 つのタイムスパンがどの程度重なるかのアルゴリズムを理解することです。ケースの絵を描くことはいつも役に立ちます。
Case 1
|------|
|=======|
Case 2
|------|
|======|
Case 3
|-------|
|===|
および順序を逆にした同等のもの。
オーバーラップは、2 つの終了時間の最小値から 2 つの開始時間の最大値を引いたものであることがわかります。(負の場合、重複はありません)。私は常にすべてのケースをチェックして、これを再確認する必要があります.
-- Function that determines how many minutes of overlap there are between two timespans
Create Function dbo.MinutesOverlap(
@Start1 as datetime, @End1 as datetime, @Start2 as datetime, @End2 as datetime
) Returns int As
Begin
Declare
@MaxStart As datetime,
@MinEnd As datetime,
@Ret int = 0
Set @MaxStart = Case When @Start1 > @Start2 Then @Start1 Else @Start2 End
Set @MinEnd = Case When @End1 > @End2 Then @End2 Else @End1 End
If @MaxStart < @MinEnd
Set @Ret = DateDiff(Minute, @MaxStart, @MinEnd)
Return @Ret
End
Select
u.UserID,
e.EventID,
Sum(dbo.MinutesOverlap(e.eventStart, e.eventEnd, a.availStart, a.availEnd))
From
Event e
Cross Join
User u
Left Outer Join
Available a
On u.UserID = a.UserID
Group By
u.UserID,
e.EventID