SQL Server 中的輸贏記錄
我正在 Microsoft SQL Server 上建構一個數據庫來自學 SQL。我是 UFC 的忠實粉絲,所以我想建立一個關於 UFC 戰士的數據庫。
我正在建造兩張桌子
fight
和fighter
. 該fighter
表將包含體重、身高、生日等統計數據,以及獲勝、失敗、平局和 NC(無比賽)的列。該fight
表將有一個winner_id 列和一個loser_id 列以及is_draw 和is_nc 列。
fight
我怎樣才能最好地在表中的winner_id/loser_id 列與表的wins 和loss 列之間創建連結fighter
?有一個警告。通常 MMA 選手會帶著在其他組織的經驗來到 UFC。所以他們在UFC之前就已經有了勝負記錄。我的數據庫只會記錄 UFC 比賽。所以我不能有那些以前的輸贏
$$ fight $$桌子。出於這個原因,我現在決定使用觸發器。 **問題:**除了觸發器之外還有更好的方法嗎?我正在考慮設置 wins 列 = 基數 + 他們的 fighter_id 列在winner_id 列中的次數。但我該怎麼做呢?我需要使用視圖嗎?
這是我創建的觸發器。
CREATE TRIGGER tr_fight_ResultUpdateFighter ON fight FOR INSERT AS BEGIN -- Win DECLARE @winner_id int DECLARE @loser_id int DECLARE @is_draw bit DECLARE @is_nc bit SELECT @winner_id = winner_id, @loser_id = loser_id, @is_draw = is_draw, @is_nc = is_nc FROM inserted --Wins UPDATE fighter SET wins = wins+1 WHERE fighter_id = @winner_id --Loss UPDATE fighter SET losses = losses+1 WHERE fighter_id = @loser_id --Draw UPDATE fighter SET draws = draws + CASE WHEN @is_draw = 1 THEN 1 ELSE 0 END WHERE fighter_id = @winner_id AND fighter_id = @loser_id --NC UPDATE fighter SET nc = nc + CASE WHEN @is_nc = 1 THEN 1 ELSE 0 END WHERE fighter_id = @winner_id AND fighter_id = @loser_id END
我將從在執行時確定統計數據開始。只有在結果太昂貴的情況下,我才會對統計數據進行非規範化:
select f1.fighter_id , count(case when f2.is_draw = 0 and f1.fighter_id = f2.winnner_id then 1 end) as #wins , count(case when f2.is_draw = 0 and f1.fighter_id = f2.looser_id then 1 end) as #loss , count(case when f2.is_draw = 1 and f1.fighter_id in (f2.winner_id, f2.looser_id) then 1 end) as #draws , ... from fighter f1 join fights f2 on f1.fighter_id in (f2.winnner_id, f2.looser_id) group by f1.fighter_id;
在您的觸發器中有一些錯誤:
第一種:平局計算
你已經寫了這個:
--Draw UPDATE fighter SET draws = draws + CASE WHEN @is_draw = 1 THEN 1 ELSE 0 END WHERE fighter_id = @winner_id AND fighter_id = @loser_id
但是這個查詢不能更新任何東西,因為
@winner_id
並且@loser_id
總是不同的。你必須AND
改變OR
第二:nc的計算
在這裡重複繪製相同的錯誤,解決方案是相同的
第三:你確定你的觸發程序只有一行嗎?
在
INSERTED
表中,您將所有行都包含在 INSERT 或 UPDATE 語句中。如果您只有如下聲明:
INSERT INTO yourtable (field list) VALUES (list of values)
您只涉及一行並且您的觸發器沒問題,但是,如果您有如下查詢:
INSERT INTO yourtable SELECT * FROM anothertable WHERE conditions
如果
SELECT * FROM
返回多行,則您的觸發器僅適用於這些行中的第一行。在這種情況下,您必須深入更改觸發程式碼,在這種情況下可能的解決方案是使用
UPDATE ... FROM
操作