问题
This is what I have tried so far:
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
The results that I am getting are:
1,30
1,45
1,65
2,20
2,50
3,40
I know I am missing something very obvious as usual
This is my most recent
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
*/
How can I fix the query so that I can get the expected results
回答1:
I don't have any PostgreSQL background but lets see if this works:
I would start this by simplifying it, by writing a query that first returns the total score by player:
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
Now, join that dataset to players to find the groups:
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
Now we have all players, their total score and their group. We want to identify the winner by group? We can use ranking functions to do this:
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
Now we just pick out the top ones in each group (rank = 1) using WHERE
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
Looks complicated? yes, but you can see have the final result is provided bit by bit. Each step of this is a 'subtable' and you can run and observe the data at each point.
来源:https://stackoverflow.com/questions/51487670/having-issues-combining-having-with-where-on-a-very-simple-query