2017-05-17 34 views
2

我有一些數據與ValidFromValidTo的日期相關聯。簡而言之:T-SQL - 隨着時間的推移跟蹤發生的事件

MembershipId | ValidFromDate | ValidToDate 
========================================== 
0001   | 1997-01-01 | 2006-05-09 
0002   | 1997-01-01 | 2017-05-12 
0003   | 2005-06-02 | 2009-02-07 

該表上有一個非聚集索引,它包含兩個日期作爲關鍵值。

我還有一個Date維度表,涵蓋從19002999的每個日期。

我想弄清楚如何從日期維度表(例如2016-01-012016-12-31)中選擇一系列日期,然後確定在每個日期有多少會員資格在該日期有效。

下面的代碼完成這項工作,但性能不是很好,我想知道是否有人有更好的方法來解決這個問題?

SELECT 
    d.DateKey 
    ,(SELECT COUNT(*) FROM Memberships AS m 
    WHERE d.DateKey between m.ValidFromDateKey and m.ValidToDateKey 
    ) AS MembershipCount 

FROM  
    DIM.[Date] AS d 

WHERE 
    d.CalendarYear = 2016 

在此先感謝您的任何建議!

回答

4

您的SQL中的邏輯大部分是正確的,您剛剛實現它很糟糕,因爲SQL喜歡做事情。你Dates表開始爲你做了已經,而不是做一個子選擇的每一行數據,改變你的邏輯,一個join和你在那裏:

select d.DateKey 
     ,count(m.MembershipID) as MembershipCount 
from DIM.[Date] as d 
    left join Memberships as m 
     on(d.DateKey between m.ValidFromDateKey and m.ValidToDateKey) 
where d.CalendarYear = 2016 
group by d.DateKey 
order by d.DateKey; 

你可能想什麼要小心確定每天要計算哪些會員資格。例如,如果您的日期是2006-05-09,那麼當天結束時應包含MembershipID 0001

問題在於,您是否計算了在整個一天中活動在任意點的會員數量,或者只是那些在特定時間活動的會員數量,比如一天的開始或結束?

然後爲您的ValidFromDate值重複此思考過程。

+0

太棒了!這是完美的 - 當我的查詢花了30秒以上時,我放棄了它,但它現在在1秒內全年運行。 感謝您對日期的評論。我只需要知道在每一天的任何時間,會員資格是否有效,並且ValidTo/From日期包含在內,因此您的查詢就會顯示。 – triplestones

+0

哇!如果這給了你所需要的表現,那麼這是一條好路。還有其他的方法,當非等值線需要太長時間。 –

+0

@triplestones SQL使用數據集合工作,因此非常擅長將數據集合在一起。表格只是一組數據。當你在你的主'select'中放置另一個'select'語句時,它會針對返回的每一行運行,而不僅僅是一次和'連接'在一起。爲了進一步閱讀,請查看「Set Based Thinking」 – iamdave

相關問題