3

我昨天在一次工作面试中遇到了这个问题,虽然它看起来很直接,但我无法弄清楚,这让我整晚都在想它。

系统记录有关拼字游戏联赛的数据,其中有一个 members 表、一个 games 表和一个加入 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 的获胜次数?

4

4 回答 4

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;

看到这个 SQLFiddle

于 2013-02-08T04:58:53.247 回答
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上的平局是损失

于 2013-02-08T04:58:13.943 回答
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()允许在拼字游戏中可能(如果不太可能)建立联系的可能性。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

看到这个SQL Fiddle

于 2013-02-08T04:56:50.470 回答
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;

这些查询不会将第一名的平局视为获胜。

我创建了一个MySQL SQL Fiddle 演示和一个SQL Server SQL Fiddle 演示

于 2013-02-08T05:04:52.663 回答