Sql-Server

SQL Server 中的輸贏記錄

  • June 14, 2018

我正在 Microsoft SQL Server 上建構一個數據庫來自學 SQL。我是 UFC 的忠實粉絲,所以我想建立一個關於 UFC 戰士的數據庫。

我正在建造兩張桌子fightfighter. 該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操作

引用自:https://dba.stackexchange.com/questions/157830