我昨天在面试时遇到了这个问题,虽然看起来很顺利但我无法弄清楚它是否让我整夜都在想着它。
系统记录拼字联盟的数据,有成员表,游戏表和加入的member_games表。
members: member_id, name : pk(member_id)
member_games: game_id, member_id, score : pk(game_id, member_id)
games: game_id, location, date : pk(game_id)
members
1, mick
2, keith
3, charlie
member_games
1, 1, 50
1, 2, 60
2, 1, 45
2, 3, 105
3, 1, 30
3, 3, 120
game
1, london, 2012-12-01
2, richmond, 2012-12-02
3, leeds, 2012-12-03
如何制定SQL查询以查找member_id
= 1的获胜次数?
答案 0 :(得分:4)
查询以查找member_id = 1
,
SELECT COUNT(1) "No. of Wins"
FROM (SELECT game_id, member_id, score
FROM member_games b
WHERE score =
(SELECT max(score) from member_games WHERE game_id = b.game_id)) A
WHERE member_id = 1;
答案 1 :(得分:2)
关键是首先对member_games进行分组并获得最高分,然后将其连接回member_games表以获取member_id。
事实是你需要一个左联盟才能看到Member_id赢了0场比赛。
SELECT
member_games.member_id
,COUNT(BestScore.game_id)
FROM member_games
LEFT JOIN
(
SELECT game_id, MAX(score) AS HighestScore FROM member_games GROUP BY Game_ID
) BestScore ON member_games.Score = BestScore.HighestScore
AND member_games.game_id = BestScore.game_id
WHERE member_games.member_id = 1
GROUP BY member_games.member_id;
这里是SQL Fiddle作为MySQL
此解决方案将关系计为胜利,但它应该适用于任何SQL服务器。 Rank功能在Microsoft SQL Server 2005及更高版本中可用。
为了完整性,这是一个更复杂的查询,不将关系计为胜利:
SELECT
member_games.member_id
,COUNT(BestScore.game_id)
FROM member_games
LEFT JOIN
(
SELECT member_games.game_id, HighestScore
FROM member_games
LEFT JOIN
(
SELECT game_id, MAX(score) AS HighestScore FROM member_games GROUP BY Game_ID
) BestScore ON member_games.Score = BestScore.HighestScore
AND member_games.game_id = BestScore.game_id
GROUP BY game_id, HighestScore
HAVING count(1) = 1
) BestScore ON member_games.Score = BestScore.HighestScore
WHERE member_games.member_id = 1
GROUP BY member_games.member_id;
在SQL Fiddle上与MySQL失去联系
答案 2 :(得分:1)
这应该这样做(SQL Server语法)
SELECT member_id
,COUNT(*) Wins
FROM (
SELECT member_id
,RANK() OVER (PARTITION BY Game_Id ORDER BY score DESC) Position
FROM member_games
) Positions
WHERE Position=1
AND
member_id=1
GROUP BY member_id
RANK()
允许Scrabble中可能存在关联的可能性(如果不可能)。 ROW_NUMBER()
可能会在无法达到平局的游戏中提供小的性能提升。
此方法可以轻松扩展,以显示所有位置
SELECT member_id
,Position
,COUNT(*) Games
FROM (
SELECT member_id
,RANK() OVER (PARTITION BY Game_Id ORDER BY score DESC) Position
FROM member_games
) Positions
WHERE member_id=1
GROUP BY member_id
,Position
请参阅this SQL小提琴
答案 3 :(得分:1)
以下查询将为您提供member_id 1的获胜次数。
select count(*) as number_of_wins
from member_games as mg1
where member_id = 1
and not exists (select 1
from member_games as mg2
where mg2.game_id = mg1.game_id
and mg2.member_id <> mg1.member_id
and mg2.score >= mg1.score);
以下查询将为您提供各自获胜次数的成员列表。
select m.*,
(select count(*) from member_games as mg1
where member_id = m.member_id
and not exists (select 1
from member_games as mg2
where mg2.game_id = mg1.game_id
and mg2.member_id <> mg1.member_id
and mg2.score >= mg1.score)
) as number_of_wins
from members as m;
这些查询不会将第一名的关系视为胜利。