【发布时间】:2015-05-30 21:55:06
【问题描述】:
对于体育比赛,人们要么与另一队 2 名球员成对比赛,我想输出一个特定球员面对的每个对手的列表,以及比赛中的赢、平和输数特定玩家和那个对手之间的关系。
例如,如果结果是:
- 玩家 1 和玩家 2 2-1 玩家 3 和玩家 4
- 球员 3 和球员 1 1-0 球员 2 和球员 4
- 玩家 2 和玩家 4 4-2 玩家 1 和玩家 3
- 球员 1 和球员 4 0-0 球员 3 和球员 2
我希望玩家 1 的输出为:
- 玩家 2,W1 D1 L1
- 玩家 3,W1 D1 L0
- 玩家 4,W2 D0 L1
事实证明,这很难实现。 我的数据被组织成两张表,一张是所有玩家的表(Players),一张是分数表(Scores)。
Players 有字段 PlayerID 和 PlayerName。
Scores 具有 Player1、Player2、Player3、Player4 和 Score 字段,其中每个 Player 字段都可以包含任何 PlayerID(因此任何给定的 ID 可能会根据行出现在不同的列中),并且会存储 Score,以便如果小于 21,玩家 1 和 2 输,如果大于 21,他们赢。
这个查询有什么问题?显然它返回 0。
SELECT opponent as opp, COUNT(result='win') as c1, COUNT(result='draw') as c2, COUNT(result='loss') as c3
FROM (SELECT
CASE
WHEN '$player' IN(Players1.PlayerName, Players2.PlayerName) THEN Players3.PlayerName
WHEN '$player' IN(Players3.PlayerName, Players4.PlayerName) THEN Players1.PlayerName
ELSE 'NA'
END as opponent,
CASE
WHEN '$player' IN(Players1.PlayerName, Players2.PlayerName)
THEN
CASE
WHEN Scores.Score > 21 THEN 'win'
ELSE 'NA'
END as result,
CASE
WHEN Scores.Score < 21 THEN 'loss'
ELSE 'NA'
END as result,
WHEN '$player' IN(Players3.PlayerName, Players4.PlayerName)
THEN
CASE
WHEN Scores.Score < 21 THEN 'win'
ELSE 'NA'
END as result,
CASE
WHEN Scores.Score > 21 THEN 'loss'
ELSE 'NA'
END as result,
WHEN Scores.Score = 21 THEN 'draw'
ELSE 'NA'
END as result,
FROM Scores
INNER JOIN Players Players1 ON Scores.Player1=Players1.PlayerID
INNER JOIN Players Players2 ON Scores.Player2=Players2.PlayerID
INNER JOIN Players Players3 ON Scores.Player3=Players3.PlayerID
INNER JOIN Players Players4 ON Scores.Player4=Players4.PlayerID
WHERE Players1.PlayerName = '$player' OR Players2.PlayerName = '$player' OR Players3.PlayerName = '$player' OR Players4.PlayerName = '$player'
UNION ALL
SELECT
CASE
WHEN '$player' IN(Players1.PlayerName, Players2.PlayerName) THEN Players4.PlayerName
WHEN '$player' IN(Players3.PlayerName, Players4.PlayerName) THEN Players2.PlayerName
ELSE 'NA'
END as opponent,
CASE
WHEN '$player' IN(Players1.PlayerName, Players2.PlayerName) AND Scores.Score > 21 THEN 'win'
WHEN '$player' IN(Players1.PlayerName, Players2.PlayerName) AND Scores.Score < 21 THEN 'loss'
WHEN '$player' IN(Players3.PlayerName, Players4.PlayerName) AND Scores.Score < 21 THEN 'win'
WHEN '$player' IN(Players3.PlayerName, Players4.PlayerName) AND Scores.Score > 21 THEN 'loss'
WHEN Scores.Score = 21 THEN 'draw'
ELSE 'NA'
END as result,
FROM Scores
INNER JOIN Players Players1 ON Scores.Player1=Players1.PlayerID
INNER JOIN Players Players2 ON Scores.Player2=Players2.PlayerID
INNER JOIN Players Players3 ON Scores.Player3=Players3.PlayerID
INNER JOIN Players Players4 ON Scores.Player4=Players4.PlayerID
WHERE Players1.PlayerName = '$player' OR Players2.PlayerName = '$player' OR Players3.PlayerName = '$player' OR Players4.PlayerName = '$player'
) AS SUBQUERY
GROUP BY opp
【问题讨论】:
-
是否有可能重构您的数据库架构?
-
不幸的是,数据库不是我的,还有许多其他历史查询依赖于它保留其当前模式。我可能可以在其他地方创建一个具有不同布局的副本,但这似乎是不必要的浪费,特别是考虑到数据库的大小。