mySQL子查詢計算勝率
我有一個表,我儲存了一個隨機骰子遊戲的數據,如果兩個骰子之間的總和為 7,你就贏了。這是表格:
我需要顯示每個玩家的獲勝百分比,這是現在的查詢,但它不起作用,它為每個玩家返回相同的百分比:
SELECT DISTINCT player_id, ROUND(((SELECT COUNT(id_game) FROM game WHERE result = 'WIN' ) / (SELECT COUNT(id_game) FROM game )) * 100 ) AS percentage FROM game group by player_id
你認為有可能做到這一點嗎?我開始懷疑了
SELECT player_id, COUNT(result) total, ROUND(100 * SUM(result = 'WIN') / COUNT(result)) winning_percent, ROUND(100 * SUM(result = 'LOSE') / COUNT(result)) loosing_percent FROM game GROUP BY player_id;
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=a04d576b918c392f90c1d835fd1a6f51
我所做的如下(下面的所有程式碼都可以在這裡找到——另一種解決方案可以在這裡找到):
解決方案(所問問題):
CREATE TABLE score ( id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, result CHAR(1) NOT NULL, die_1 TINYINT UNSIGNED NOT NULL, die_2 TINYINT UNSIGNED NOT NULL, player_id INTEGER NOT NULL, CONSTRAINT result_w_l_ck CHECK (result IN ('W', 'L')), CONSTRAINT die_1_throw_ck CHECK (die_1 BETWEEN 1 AND 6), CONSTRAINT die_2_throw_ck CHECK (die_2 BETWEEN 1 AND 6) );
請注意
NOT NULL
要求和其他約束 - 它們不僅可以保護數據的完整性(您的數據庫是您防止垃圾輸入的最後一道防線!),它還有助於優化器選擇最佳計劃。請注意,CHECK
在 MySQL 版本 >= 8.0.16 之前不會強制執行約束 - 令人難以置信的是,在此之前的版本會“解析”它們但不強制執行它們 - 你一定喜歡 MySQL!填充表格:
INSERT INTO score VALUES (1, 'L', 4, 4, 9), (2, 'L', 4, 5, 7), (3, 'W', 4, 3, 9), (4, 'L', 2, 3, 9), (5, 'W', 6, 1, 7), (6, 'W', 1, 6, 7), (7, 'L', 1, 3, 7);
然後我建立(注意建立)以下查詢:
SELECT player_id, SUM(CASE WHEN result = 'W' THEN 1 ELSE 0 END) AS wins, SUM(CASE WHEN result = 'L' THEN 1 ELSE 0 END) AS losses, COUNT(player_id) AS cnt, (SUM(CASE WHEN result = 'W' THEN 1 ELSE 0 END))/(COUNT(player_id)) AS w_proportion, ROUND((SUM(CASE WHEN result = 'W' THEN 1 ELSE 0 END))/(COUNT(player_id)) * 100, 2) AS w_percent FROM score GROUP BY player_id ORDER BY player_id;
結果:
player_id wins losses cnt w_proportion w_percent 7 2 2 4 0.5000 50.00 9 1 2 3 0.3333 33.33
因此,當您向下移動查詢(以及跨結果)時,您可以跟踪最終結果是如何得出的。
在這裡要非常小心 - MySQL 執行 INTEGER 劃分與其他系統不同 - SQL 標準要求- 請參閱此處PostgreSQL 1 fiddle
5/2 = 2
的底部- 另外,請查看如何通過使用強制轉換獲得最終結果(SQL 的 PostgreSQL 簡寫標準。::<data_type>``CAST (variable AS data_type>)
此外,MySQL 使用另一個(!)非標準“技巧”來允許對布爾值求和——正如你從 PostgreSQL 小提琴中看到的那樣,這在其他伺服器上不起作用——再次,要小心!
1 PostgreSQL 幾乎是最符合標準的 RDBMS - 如果您使用其他一些伺服器執行程式碼,您會發現它在這些伺服器上也會失敗。
替代解決方案(小提琴):
由於結果取決於兩次投擲的得分,因此我們實際上並不需要該列 - 如下所示:
CREATE TABLE score -- Note, no result field! ( id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, die_1 TINYINT UNSIGNED NOT NULL, die_2 TINYINT UNSIGNED NOT NULL, player_id INTEGER NOT NULL, CONSTRAINT die_1_throw_ck CHECK (die_1 BETWEEN 1 AND 6), CONSTRAINT die_2_throw_ck CHECK (die_2 BETWEEN 1 AND 6), CONSTRAINT d1_p_d2_lt_13_ck CHECK ((die_1 + die_2) < 13) );
填充:
INSERT INTO score VALUES (1, 4, 4, 9), (2, 4, 5, 7), (3, 4, 3, 9), (4, 2, 3, 9), (5, 6, 1, 7), (6, 1, 6, 7), (7, 1, 3, 7);
和 SQL:
SELECT player_id, SUM(CASE WHEN die_1 + die_2 = 7 THEN 1 ELSE 0 END) AS wins, COUNT(player_id) - SUM(CASE WHEN die_1 + die_2 = 7 THEN 1 ELSE 0 END) AS losses, SUM(CASE WHEN die_1 + die_2 = 7 THEN 1 ELSE 0 END)/COUNT(player_id) AS prop_w, ROUND(SUM(CASE WHEN die_1 + die_2 = 7 THEN 1 ELSE 0 END)/COUNT(player_id) * 100, 2) AS percent_w FROM score GROUP BY player_id ORDER BY player_id;
結果(相同):
player_id wins losses prop_w percent_w 7 2 2 0.5000 50.00 9 1 2 0.3333 33.33