SQL Query比较不同行中的数据

时间:2013-02-08 04:46:08

标签: mysql sql

我昨天在面试时遇到了这个问题,虽然看起来很顺利但我无法弄清楚它是否让我整夜都在想着它。

系统记录拼字联盟的数据,有成员表,游戏表和加入的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 个答案:

答案 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;

See this SQLFiddle

答案 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;

这些查询不会将第一名的关系视为胜利。

我创建了MySQL SQL Fiddle demoSQL Server SQL Fiddle demo