我有一些与ValidFrom
和ValidTo
日期相关的数据。简单来说:
MembershipId | ValidFromDate | ValidToDate
==========================================
0001 | 1997-01-01 | 2006-05-09
0002 | 1997-01-01 | 2017-05-12
0003 | 2005-06-02 | 2009-02-07
此表上有一个非聚集索引,其中包含两个日期作为键值。
我还有一个日期维度表,涵盖从1900
到2999
的每个日期。
我正在试图弄清楚如何从日期维度表中选择一系列日期(比方说2016-01-01
到2016-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
提前感谢任何建议!
答案 0 :(得分:5)
你的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
值重复此思维过程。