Проблемы с использованием group by для получения максимального значения для двух таблиц - PullRequest
0 голосов
/ 02 марта 2019

Я пытался решить проблему в течение очень долгого времени, и я не добиваюсь никакого прогресса.В основном у меня есть две таблицы, players и matches.Каждый игрок в players имеет уникальный player_id, а также group_id, который определяет, к какой группе он / она принадлежит.В каждом матче в matches есть player_id с двумя игроками, first_player и second_player, которые всегда принадлежат к одной группе.first_score соответствует баллу, который набрал first_player, а second_score соответствует баллу, который набрал second_player.Матч выигрывает тот, кто забивает больше.Вот две таблицы:

create table players (
      player_id integer not null unique,
      group_id integer not null
);

create table matches (
      match_id integer not null unique,
      first_player integer not null,
      second_player integer not null,
      first_score integer not null,
      second_score integer not null
);

Теперь я пытаюсь получить игроков с наибольшим количеством побед в каждой группе, идентификатором их группы и количеством побед.Так, например, если есть три группы, результат будет примерно таким:

Group    Player    Wins
1        24        23
2        13        25
3        34        20

Вот что у меня есть сейчас

SELECT p1.group_id AS Group, p1.player_id AS Player, COUNT(*) AS Wins
FROM players p1, matches m1
WHERE (m1.first_player = p1.player_id AND m1.first_score > m1.second_score) 
   OR (m1.second_player = p1.player_id AND m1.second_score > m1.first_score)
GROUP BY p1.group_id
HAVING COUNT(*) >= (
            SELECT COUNT(*)
            FROM players p2, matches m2
            WHERE p2.group_id = p1.group_id AND
                ((m2.first_player = p2.player_id AND m2.first_score > m2.second_score) 
                   OR (m2.second_player = p2.player_id AND m2.second_score > m2.first_score))
)

Моя идея состоит в том, чтобы выбирать только игроков, чьивыигрыши больше или равны выигрышам всех других игроков в его группе.Есть некоторая синтаксическая проблема с моим запросом.Я думаю, что я тоже неправильно использую GROUP BY.

Существует также проблема ничьей в количестве побед, когда я должен просто получить игрока с наименьшим player_id.Но я еще даже не дошел до этого.Буду очень признателен за вашу помощь, спасибо!

РЕДАКТИРОВАТЬ 1

У меня есть несколько примеров данных, к которым я выполняю свой запрос.

SELECT * FROM players дает мне это:

Player_ID Group_ID
100        1
200        1
300        1
400        2
500        2
600        3
700        3

SELECT * FROM matches дает мне это:

match_id first_player second_player first_score second_score
1        100          200           10          20
2        200          300           30          20
3        400          500           30          10
4        500          400           20          20
5        600          700           20          10

Итак, запрос должен вернуть:

Group    Player    Wins
1        200       2
2        400       1
3        600       1

Выполнение запроса как есть возвращает следующую ошибку:

ERROR:  column "p1.player_id" must appear in the GROUP BY clause or be used in an aggregate function

Теперь я понимаю, что мне нужно указать player_id в предложении GROUP BY, если я хочу использовать его в SELECT (илиHAVING), но я не хочу группировать по идентификатору игрока, только по идентификатору группы.

Даже если я добавлю p1.player_id к GROUP BY в моем внешнем запросе, я получу ... правильныйответь на самом деле.Но я немного смущен.Разве Group By не агрегирует таблицу по этому столбцу?Говоря логически, я хочу группировать только по p1.group_id.

Кроме того, если бы у меня было несколько игроков в группе с наибольшим количеством побед, как я могу просто оставить игрока с самым низким * 1053?*?

Редактировать 2

Если я изменю таблицу matches на такую, что для группы 1 появятся два игрока с 1 выигрышем в каждом, результат запроса опускаетсяГруппа 1 от результата в целом.Итак, если моя таблица matches:

match_id first_player second_player first_score second_score
1        100          200           10          20
2        200          300           10*         20
3        400          500           30          10
4        500          400           20          20
5        600          700           20          10

, я ожидаю, что результат будет

Group    Player    Wins
1        200       1
1        300       1
2        400       1
3        600       1

Однако я получаю следующее:

Group    Player    Wins
2        400       1
3        600       1

Обратите внимание, что желаемый результат -

Group    Player    Wins
1        200       1
2        400       1
3        600       1

Так как я хочу взять игрока с наименьшим player_id в случае ничьей.

Ответы [ 2 ]

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

Это работает, когда вы добавляете player_id в GROUP BY, потому что вы знаете, что каждый игрок играет только в одной группе.Таким образом, вы группируются по игроку в определенной группе.Вот почему, по логике вещей, вы можете добавить player_id в GROUP BY.

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

попробуйте, как показано ниже

with cte as
   ( 
  select p.Group_ID,t1.winplayer,t1.numberofwin
row_number()over(partition by p.Group_ID order by t1.numberofwin desc,t1.winplayer) rn  from players p join  
    (
     SELECT count(*) as numberofwin,
      case when first_score >second_score then first_player 
      else second_player end as winplayer
      FROM matches group by case when first_score >second_score then first_player 
      else second_player end
    ) t1 on p.Player_ID =t1.winplayer
 ) select * from cte where rn=1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...