将“while”替换为基于集合的操作

时间:2016-02-25 15:48:55

标签: sql sql-server while-loop

我正在使用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。我有什么方法可以更快地完成这项工作吗?

感谢您的帮助!

3 个答案:

答案 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表。