我正在爲我們運行的網站編寫一個成就模塊。這段代碼將在給定的時間範圍結束時在SQL Server上運行,以獎勵成果(下次訪問該網站時將通過客戶端通知)。如何替換嵌套遊標?
所以我需要看看所有的團隊和所有的「最終」成就(這是獨立的團隊)。每項成就都有一個或多個必須符合的規則。一旦我確定成績通過了,我就會將該成就獎給該團隊的所有參與者。
我是通過遊標處理這一點,我得到了一個錯誤,所以當我去谷歌問題,我上的論壇上無休止的鏈接「你傻乎乎$ &#$爲什麼你使用遊標」(意譯) 。我想,當我解決我的問題的時候,我可能會更換我使用的基於集合的方法(如果可能的話)。
我發現的另一個例子是所有基本的更新場景,在表格上使用單個嵌套循環來實現相互之間的密鑰交互,老實說,我不會考慮在這些場景中使用遊標來開始。
我下面的內容是而不是完全在句法上是正確的,但我可以通過玩弄自己來解決這個問題。這應該給的什麼,我試圖完成一個清晰的思路,但是:
declare @TimeframeID int;
declare @AchievementID int;
declare @q1 int;
declare @q2 int;
declare @TeamID int;
declare @TotalReg int;
declare @TotalMin int;
declare @AvgMin decimal(10, 2);
declare @AggType varchar(50);
declare @Pass bit = 1;
declare @Email varchar(50);
declare @ParticipantID int;
select @TimeframeID = MAX(TimeframeID) from Timeframes
where IsActive = 1;
declare team_cur CURSOR FOR
select
t.TeamID,
(select COUNT(1) from Registrations r
where r.TeamID = t.TeamID and r.TimeframeID = @TimeframeID) TotalReg,
(select SUM(Minutes) from Activities a
inner join Registrations r on r.RegistrationID = a.RegistrationID
where r.TeamID = t.TeamID and r.TimeframeID = @TimeframeID) TotalMin
from Teams t
where Active = 1
group by TeamID;
declare ach_cur CURSOR FOR
select AchievementID from luAchievements
where TimeframeID = @TimeframeID and AchievementType = 'End';
declare rule_cur CURSOR for
select Quantity1, Quantity2, AggregateType
from AchievementRule_Links arl
inner join luAchievementRules ar on ar.RuleID = arl.RuleID
where arl.AchievementID = @AchievementID;
open team_cur;
fetch next from team_cur
into @TeamID, @TotalReg, @TotalMin;
while @@FETCH_STATUS = 0
begin
open ach_cur;
fetch next from ach_cur
into @AchievementID;
while @@FETCH_STATUS = 0
begin
open rule_cur;
fetch next from rule_cur
into @q1, @q2, @AggType;
while @@FETCH_STATUS = 0
begin
if @AggType = 'Total'
begin
if @q1 > @TotalReg
begin
set @Pass = 0;
end
end
else if @AggType = 'Average'
begin
print 'do this later; need to get specs';
end
fetch next from rule_cur
into @q1, @q2, @AggType;
end
close rule_cur;
deallocate rule_cur;
-- if passed, award achievement to all team members
if @Pass = 1
begin
declare reg_cursor cursor for
select max(p.Email) from Participants p
inner join Registrations reg on reg.ParticipantID = p.ParticipantID
where reg.TeamID = @TeamID;
open reg_cursor;
fetch next from reg_cursor
into @Email;
while @@FETCH_STATUS = 0
begin
exec ProcessAchievement @AchievementID, @Email, 0;
fetch next from reg_cursor
into @Email;
end
close reg_cursor;
deallocate reg_cursor;
-- award achievement to team
exec ProcessTeamAchievement @AchievementID, @TeamID;
end
fetch next from ach_cur
into @AchievementID;
end
close ach_cur;
deallocate ach_cur;
fetch next from team_cur
into @TeamID, @TotalReg, @TotalMin;
end
close team_cur;
deallocate team_cur;
是否有一個基於集合的替代我在這裏做什麼?我需要補充的是,這是針對一小部分記錄運行的,所以表現並不是我關心的問題;未來龐大更新的最佳實踐。
感謝您的幫助!當然,這是一種更有效和正確的做事方式。 – Ryan