Найти имя игрока, который забил максимальное количество голов? - PullRequest
0 голосов
/ 21 марта 2019

Я должен найти имя максимального забившего гол и забитых голов.

GOAL_DETAILS(GOAL_ID,PLAYER_ID,TEAM_ID,GOAL_TIME)

PLAYER_MAST(PLAYER_ID,PLAYER_NAME)

Я сделал это, используя join, но не смог сделать это с помощью подзапроса. Пожалуйста, помогите.

1-й подход:

SELECT PLAYER_ID,
       PLAYER_NAME
FROM   PLAYER_MAST 
WHERE  PLAYER_ID IN ( SELECT PLAYER_ID,
                             COUNT(PLAYER_ID) 
                      FROM   GOAL_DETAILS
                      GROUP BY PLAYER_ID
                      HAVING COUNT(PLAYER_ID)=(SELECT MAX(COUNT(*))
                                               FROM GOAL_DETAILS
                                               GROUP BY PLAYER_ID)
                    );

2-й подход:

SELECT PLAYER_ID,
       PLAYER_NAME
FROM   PLAYER_MAST 
WHERE  PLAYER_ID IN (SELECT PLAYER_ID,
                            COUNT(PLAYER_ID) 
                     FROM   GOAL_DETAILS
                     GROUP BY PLAYER_ID
                     HAVING COUNT(PLAYER_ID)=MAX(COUNT(PLAYER_ID))
                    );

3-й подход:

SELECT PLAYER_ID,
       PLAYER_NAME
FROM   PLAYER_MAST 
WHERE  PLAYER_ID IN (SELECT PLAYER_ID,
                            MAX(COUNT(*))
                     FROM   GOAL_DETAILS
                     GROUP BY PLAYER_ID
                    ) ;

Я знаю, что они будут печатать только имена, а не общее количество забитых голов, но они даже не будут печатать имена.

Где я делаю это неправильно?

Ответы [ 3 ]

0 голосов
/ 21 марта 2019
with goal_details(goal_id,player_id,team_id,goal_time) as (
select 1, 1, 1, 10 from dual union all
select 2, 2, 2, 20 from dual union all
select 3, 2, 2, 30 from dual union all
select 3, 3, 3, 30 from dual
),
player_mast(player_id,player_name) as (
select 1, 'First'  from dual union all
select 2, 'Second' from dual union all
select 3, 'Thirth' from dual
)
select
max(p.player_id)   keep (dense_rank last order by count(*))              as max_scorer_id,
max(p.player_name) keep (dense_rank last order by count(*), p.player_id) as max_scorer_mame,
max(count(*))                                                            as max_count
from goal_details d
join player_mast  p on p.player_id = d.player_id
group by p.player_id, p.player_name;

MAX_SCORER_ID MAX_SC  MAX_COUNT
------------- ------ ----------
            2 Second          2
0 голосов
/ 21 марта 2019

Где я делаю это неправильно?

Вы получаете ORA-00913: too many values исключение

Это потому, что у вас есть синтаксис:

WHERE value1 IN ( SELECT value1, value2 ....

и ваш IN фильтр должны иметь то же количество значений слева, что и в списке справа;поэтому удалите часть COUNT(PLAYER_ID) возвращаемых значений вашего подзапроса:

WHERE PLAYER_ID IN ( SELECT PLAYER_ID FROM ....

Тогда ваша первая попытка должна сработать:

SELECT PLAYER_ID,
       PLAYER_NAME
FROM   PLAYER_MAST 
WHERE  PLAYER_ID IN ( SELECT PLAYER_ID
                      FROM   GOAL_DETAILS
                      GROUP BY PLAYER_ID
                      HAVING COUNT(PLAYER_ID)=(SELECT MAX(COUNT(*))
                                               FROM GOAL_DETAILS
                                               GROUP BY PLAYER_ID)
                    );

db <> fiddle

0 голосов
/ 21 марта 2019

Я бы использовал ROW_NUMBER здесь:

WITH cte AS (
    SELECT p.PLAYER_ID, p.PLAYER_NAME, COUNT(*) AS cnt,
        ROW_NUMBER() OVER (ORDER BY COUNT(*) DESC) rn
    FROM PLAYER_MAST p
    INNER JOIN GOAL_DETAILS g
        ON p.PLAYER_ID = g.PLAYER_ID
    GROUP BY p.PLAYER_ID, p.PLAYER_NAME
)

SELECT PLAYER_ID, PLAYER_NAME
FROM cte
WHERE rn = 1;

Если вы хотите захватить всех игроков, привязанных к первому месту, тогда замените ROW_NUMBER на RANK.Обратите внимание, что я агрегировал оба значения PLAYER_ID и PLAYER_NAME, на случай, если два игрока могут иметь одно и то же имя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...