Reputation: 704
My dataset looks like this:
TEAM_ID PLAYER_ID NUM_POINTS
21 39 20
21 50 10
21 67 10
22 74 0
22 73 0
I want to get a subset of the data where each team has a clear "winner", that is, if I group by team ID there is exactly ONE player who has more points than all the other players. If there is a tie between two or more players on the team, I do not want them to be included in the subset. I tried out a query but the number or rows I'm getting in my subset seems way too high so I think I'm making a mistake. Here's my query:
WITH ADD_MAX_POINTS_VALUES_TO_TEAM AS (
SELECT
T1.TEAM_ID,
MAX(T1.NUM_POINTS) AS MAX_POINTS_FOR_TEAM,
FROM MY_TABLE T1
GROUP BY T1.TEAM_ID
), GET_SUBSET AS (
SELECT T1.TEAM_ID
T1.PLAYER_ID
T2.MAX_POINTS_FOR_TEAM
FROM MY_TABLE T1 INNER JOIN ADD_MAX_POINTS_VALUES_TO_TEAM T2
ON T1.B1_BUS_PRTNR_NBR = T2.B1_BUS_PRTNR_NBR
WHERE T1.NUM_POINTS = T2.MAX_POINTS_FOR_TEAM
GROUP BY 1, 2, 3
HAVING COUNT(*) = 1 -- > HERE I AM TRYING TO SAY THERE IS ONE UNIQUE PLAYER ON THE TEAM WITH THE MAX SCORE
),
SELECT COUNT(*) FROM GET_SUBSET
Any help is appreciated, let me know if I need to provide more info.
Thanks!!
Upvotes: 3
Views: 80
Reputation: 60482
This returns rows with unique best players:
SELECT *
FROM MY_TABLE
QUALIFY
RANK() OVER (PARTITION BY TEAM_ID
ORDER BY NUM_POINTS DESC WITH TIES HIGH) = 1
The WITH TIES HIGH
option is a Teradata extension implementing modified competition ranking.
Standard ranking (RANK [WITH TIES LOW]
) assigns two gold medals when two best players exist, while this assigns two silver medals -> If there's a rank 1
the best points are unique.
Upvotes: 3
Reputation: 5139
We can use a subquery :
select *
from MY_TABLE a
where a.num_points > all (select op.num_points
from MY_TABLE op
where a.team_id=op.team_id
and a.player_id<>op.player_id)
Upvotes: 2
Reputation: 522506
We can use the RANK()
window function here:
WITH cte1 AS (
SELECT t.*, RANK() OVER (PARTITION BY TEAM_ID ORDER BY NUM_POINTS DESC) rnk
FROM MY_TABLE t
),
cte2 AS (
SELECT TEAM_ID
FROM cte1 t1
WHERE rnk = 1 AND
NOT EXISTS (
SELECT 1
FROM cte1 t2
WHERE t2.TEAM_ID = t1.TEAM_ID AND
t2.PLAYER_ID <> t1.PLAYER_ID AND
t2.rnk = 1
)
)
SELECT t1.TEAM_ID, t1.PLAYER_ID, t1.NUM_POINTS
FROM MY_TABLE t1
INNER JOIN cte2 t2
ON t2.TEAM_ID = t1.TEAM_ID;
The first CTE assigns a rank per team based on the number of points. The second CTE then identifies teams having only a single rank 1 record.
Upvotes: 2