在非常简单的QUERY上将HAVING与WHERE结合使用时遇到问题

时间:2018-07-23 21:51:57

标签: postgresql

I have the following simple excercise

这是我到目前为止尝试过的:

SELECT group_id, player_id as winner_id
/* 
,sum(M1.first_score + M2.second_score), sum(M2.first_score + M1.second_score)
*/

FROM players as P1

LEFT JOIN matches as M1 
ON M1.first_player = P1.player_id

LEFT JOIN matches as M2
ON M2.second_player = P1.player_id

LEFT JOIN matches as M3
ON M3.first_player = P1.player_id

LEFT JOIN matches as M4
ON M4.second_player = P1.player_id


--WHERE P1.player_id is not null /*or P2.player_id is not null*/

GROUP BY group_id, P1.player_id

/*
HAVING 
sum(M1.first_score + M2.second_score) > sum(M2.first_score + M1.second_score)
OR
sum(M3.first_score + M4.second_score) > sum(M4.first_score + M3.second_score)
*/

ORDER BY group_id ASC, player_id ASC

我得到的结果是:

1,30
 1,45
 1,65
 2,20
 2,50
 3,40

我知道我像往常一样缺少明显的东西

这是我最近的

attempt

-- write your code in PostgreSQL 9.4
SELECT 
group_id,  player_id as winner_id

/* 
,sum(M1.first_score + M2.second_score), sum(M2.first_score + M1.second_score)
*/

FROM players as P1

LEFT JOIN matches as M1 
ON M1.first_player = P1.player_id

LEFT JOIN matches as M2
ON M2.second_player = P1.player_id

LEFT JOIN matches as M3
ON M3.first_player = P1.player_id

LEFT JOIN matches as M4
ON M4.second_player = P1.player_id


GROUP BY group_id, P1.player_id, M1,M2,M3,M4

/*
HAVING 
(M1 is not null) OR (M2 is not null) OR (M3 is not null) OR (M4 is not null)
*/

/*
HAVING 
sum(M1.first_score + M2.second_score) > sum(M2.first_score + M1.second_score)
OR
sum(M3.first_score + M4.second_score) > sum(M4.first_score + M3.second_score)
*/

ORDER BY group_id ASC
/*, player_id DESC
*/

如何修复查询,以便获得预期的结果

1 个答案:

答案 0 :(得分:2)

我没有任何PostgreSQL背景,但让我们看看是否可行:

首先,我将通过编写一个首先返回玩家总得分的查询来简化它:

SELECT player_id, SUM(score) score
FROM (
  SELECT first_player as player_id, first_score as score
  FROM matches
  UNION ALL
  SELECT second_player, second_score
  FROM matches
)
GROUP BY player_id

现在,将该数据集与玩家一起找到组:

SELECT w.player_id, p.group_id, w.score
FROM
(
  SELECT player_id, SUM(score) score
  FROM (
    SELECT first_player as player_id, first_score as score
    FROM matches
    UNION ALL
    SELECT second_player, second_score
    FROM matches
  )
  GROUP BY player_id
) as w
inner join players p
on p.player_id = w.player_id

现在我们有了所有球员,他们的总得分和他们的队伍。我们要按组确定获胜者吗?我们可以使用ranking函数来做到这一点:

SELECT 
w.player_id, 
p.group_id, 
w.score, 
RANK() OVER (PARTITION BY p.group_id ORDER BY score DESC) as group_placement
FROM
(
  SELECT player_id, SUM(score) score
  FROM (
    SELECT first_player as player_id, first_score as score
    FROM matches
    UNION ALL
    SELECT second_player, second_score
    FROM matches
  )
  GROUP BY player_id
) as w
inner join players p
on p.player_id = w.player_id

现在,我们只需使用WHERE选出每个组中排名最高的(排名= 1)

  SELECT 
  player_id, 
  group_id
  FROM
  (
      SELECT 
      w.player_id, 
      p.group_id, 
      w.score, 
      RANK() OVER (PARTITION BY p.group_id ORDER BY score DESC) as group_placement
      FROM
      (
        SELECT player_id, SUM(score) score
        FROM (
          SELECT first_player as player_id, first_score as score
          FROM matches
          UNION ALL
          SELECT second_player, second_score
          FROM matches
        )
        GROUP BY player_id
      ) as w
      inner join players p
      on p.player_id = w.player_id
    ) as gp
    WHERE group_placement = 1

看起来复杂吗?是的,但是您可以看到最终的结果是逐点提供的。每个步骤都是一个“子表”,您可以在每个点上运行和观察数据。