我正在使用SQL Server 2012.我有一个查询,它将查看给定的月份,并通过检查该成员在给定月份的注册范围来确定该月份中哪些成员有效/有效。这是查询的样子:
select monthstart, monthend
into #tmp
from monthtable --This table contains the month start and end dates I need
create table #result(ID varchar(20), monthstart varchar(8))
declare @eff varchar(8)
declare @end varchar(8)
while (select count(*) from #tmp) > 0
begin
select top 1 @eff = monthstart from #tmp order by monthstart
select top 1 @end = monthend from #tmp order by monthstart
insert into #result
select ID, @eff
from members
where ymdeff <= @end and ymdend >= @eff -- Ensures the member is active for at least one day in this month
end
select * from #result
我在约8个月内看到一组约50名成员。自从我开始撰写这篇文章以来,这个查询一直在运行,它仍在继续。我认为它最终会得到正确的答案,但这需要太长时间。这似乎应该很简单,但我想不出任何其他方法来做到这一点,除了写出每个月的where语句,或者使用仍然是迭代而不是基于集合的动态sql。我有什么方法可以更快地完成这项工作吗?
感谢您的帮助!
答案 0 :(得分:2)
正如@Ajay所说,当你循环时,你忘记了临时表中的DELETE
行,所以你陷入了无限循环。
尽管完全避免循环(在SQL中可能几乎总是这样做):
SELECT
M.id,
T.monthstart
FROM
#tmp T
INNER JOIN Members M ON M.ymdeff <= T.monthend AND M.ymdend >= T.monthend
我希望ymdeff
不是VARCHAR
作为 <header id="parent">
<img id="selector" class="img-responsive" src="yourdir/here.png">
</header>
在数据库中的日期...
答案 1 :(得分:2)
您创建的循环是无限的。您需要在每次迭代时从#tmp中删除数据。
while (select count(*) from #tmp) > 0
begin
select top 1 @eff = monthstart from #tmp order by monthstart
select top 1 @end = monthend from #tmp order by monthstart
insert into #result
select ID, @eff
from members
where ymdeff <= @end and ymdend >= @eff -- Ensures the member is active
for at least one day in this month
delete #tmp where monthstart=@eff and monthend =@end
end
而不是循环,你可以使用如下的连接
select m.ID, t.monthstart from members m , #tmp t where m.ymdeff <= t.monthstart and m.ymdend >= t.monthend
答案 2 :(得分:1)
当问题包括样本数据和预期输出时,更容易回答这些问题。如果我误解了您的架构,请接受我的道歉。
<强>查询强>
SELECT
m.ID,
mt.MonthStart
FROM
MonthTable mt
INNER JOIN Members m ON m.ymdeff BETWEEN mt.MonthStart AND mt.MonthEnd
GROUP BY
m.ID,
mt.MonthStart
;
此查询将MonthTable直接连接到members表。