Reputation: 515
I'm using SQL server 2012. I have a query which will look at a given month and determine which members are active/effective during that month, by checking the enrollment span for that member for the given month. Here's what the query looks like:
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
I'm looking at a set of about 50 members for about 8 months. This query has been running since I started writing this post, and it's still going. I think it will get to the right answer eventually, but it's taking too long. This seems like it should be simple, but I can't think of any other way to do this, except writing out the where statement for each month, or using dynamic sql which would still be iterative rather than set-based. Is there any way for me to get this done more quickly?
Thank you for your help!
Upvotes: 0
Views: 98
Reputation: 5040
It's easier to answer these when the question includes sample data and expected output. So please accept my apologies if I've misinterpreted your schema.
Query
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
;
This query joins the MonthTable directly to the members table.
Upvotes: 1
Reputation: 785
The loop you have created is infinite . You need to delete the data from #tmp on each iteration .
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
instead of loop you can use joins as below
select m.ID, t.monthstart from members m , #tmp t where m.ymdeff <= t.monthstart and m.ymdend >= t.monthend
Upvotes: 2
Reputation: 47402
As @Ajay says, you forgot to DELETE
rows from your temporary table as you loop, so you're stuck in an infinite loop.
To avoid the loop altogether though (which should almost always be done when possible in SQL):
SELECT
M.id,
T.monthstart
FROM
#tmp T
INNER JOIN Members M ON M.ymdeff <= T.monthend AND M.ymdend >= T.monthend
I hope that ymdeff
isn't a date sitting in the DB as a VARCHAR
though...
Upvotes: 2