我从未在SQL Server 2008中使用触发器。所以我不知道该怎么做。
我有一个游戏应用程序,我正在跟踪所播放的问题的数量和正确回答的问题总数。我也节省了每个问题的平均停留时间。
现在我想根据正确答案的百分比来记录排名。如果有平局,我们将检查所花费的时间。我必须使用触发器完成所有这些。
id | playerID | CompetitionID | NoOfCOrrectANswers | NoOfPlayedQuestions | TimeTaken
-----------------------------------------------------------------------------------------
1 3 203 4 8 8.4
2 56 203 9 18 13
3 67 203 16 45 15
感谢任何帮助。提前谢谢。
答案 0 :(得分:2)
你可能不应该走这条路,因为更新的数量会很高。您可以将row_number()或rank()函数添加到显示竞争结果的查询中。
话虽如此,如果您认为绝对必须在表格中保留排名信息,请添加一列
alter table ATable add PlayerRank int
并在ATable上创建一个触发器
create trigger RankingTrigger on ATable
after insert, update, delete
as
-- We don't want queries in a trigger to mess up with "Rows affected"
set nocount on
-- If any of the following columns are mentioned in a query
-- Always true for insert and delete, but we will save updates
-- if we skip processing when columns participating in ranking
-- are not changed
If update (NoOfCOrrectANswers)
OR update(NoOfPlayedQuestions)
OR update(TimeTaken)
begin
-- CTE that returns primary key and rank by competition.
-- I've changed your condition (percent of correct answers)
-- As it would rank players with one correct answer over those
-- who answered 100 questions and got only one wrong. If you
-- want to change it, replace NoOfCOrrectANswers with
-- NoOfCOrrectANswers / NoOfPlayedQuestions
; with theRank as (
select ID, row_number() over (partition by CompetitionID
order by NoOfCOrrectANswers DESC,
TimeTaken DESC) rn
from ATable
-- Only changed competitions
where CompetitionID in
-- Inserted table is available in trigger and OUTPUT clause
-- of insert, update, delete statements.
-- It contains newly added/changed rows
-- We are using it here to filter only changed competitions
-- Similary, Deleted table hold a copy of removed rows for delete
-- and old values for update
(
select CompetitionID
from Inserted
union
select CompetitionID
from Deleted
)
)
update ATable
-- Update to rank from theRank CTE
set PlayerRank = theRank.rn
from ATable
-- All records participation in affected competitions
inner join theRank
on ATable.ID = theRank.ID
-- Only change if really changed
-- This part is very likely not needed. I have never tested
-- to see if it affects performance
and isnull(ATable.PlayerRank, 0) <> theRank.rn
end