Подзапрос был неправильным все это время, что мне делать? - PullRequest
0 голосов
/ 06 июня 2019

Итак, у меня есть следующая структура таблицы для системы спортивных событий

ТАБЛИЦА КОМАНД
team_id
game_id
team_name
team_logo

ТАБЛИЦА ИГРОКОВ player_id
team_id
player_name
player_mobile
player_email

Так что, когда игрок отправляет команду, регистрационные данные сохраняются на обоих столах.События могут быть чем-то вроде крикета, баскетбола, нетбола и т. Д. Иногда они не заполняют информацию об игроках, а иногда они снова отправляют свою команду, что означает, что имя команды указано.

Поэтому, когда мне нужно проверить точные детали списка команд, я использовал это:

SELECT team_id FROM `teams` WHERE `game_id`= 35 GROUP BY `team_name

Чтобы получить список людей в этих командах с одинаковыми именами, яиспользовал это:

SELECT team_id, player_name FROM `player` WHERE team_id IN (SELECT team_id FROM `teams` WHERE `game_id`= 35 GROUP BY `team_name`) AND player_name IS NOT NULL AND player_name <> ''

Проблема в том, что запрос сверху дает мне результаты, отличные от того, что я получаю снизу.Что мне нужно сделать, это получить список текущих команд, когда мне нужно.Дубликаты команд должны быть не там.Тогда мне нужен список игроков этих команд.

В настоящее время поставлен в тупик :( Помогите мне, пожалуйста.

Ответы [ 2 ]

0 голосов
/ 07 июня 2019

TL; DR

Вы можете получить желаемые результаты с помощью JOIN и DISTINCT

SELECT DISTINCT t.team_name, P.player_name 
FROM teams AS t
    INNER JOIN Players AS p
        ON p.team_id = t.team_id;

ПОЛНОЕ ОБЪЯСНЕНИЕ

Следующий запрос не является детерминированным, то есть вы можете запускать один и тот же запрос для одних и тех же данных несколько раз и получать разные результаты:

SELECT team_id 
FROM `teams` 
WHERE `game_id`= 35 
GROUP BY `team_name`;

Многие СУБД даже не позволяютэтот запрос для запуска.Вы заявили, что некоторые команды дублируются, поэтому рассмотрите следующие фиктивные данные:

team_id    team_name     game_id
------------------------------------
   1       The A-Team       35
   2       The A-Team       35
   3       The A-Team       35

Когда вы группируете по team_name, вы получаете одну группу, поэтому, если мы начнем с действительного запроса:

SELECT team_name
FROM `teams` 
WHERE `game_id`= 35 
GROUP BY `team_name`;

Мы ожидаем один результат:

team_name
--------------
The A-Team

Когда вы добавляете team_id в выборку без агрегатной функции, вам нужно выбрать одно значение для team_id,но у механизма запросов есть 3 различных значения на выбор, и ни одно из них не является более правильным, чем любое другое.Вот почему что-либо в операторе select должно содержаться внутри группы (или функционально зависеть от чего-либо) или быть частью агрегатной функции.

Состояние MySQL Docs :


В стандартном SQL запрос, включающий предложение GROUP BY, не может ссылаться на неагрегированные столбцы в списке выбора, которые не названы в предложении GROUP BY.Например, этот запрос недопустим в стандартном SQL, поскольку столбец имени в списке выбора не отображается в GROUP BY:

SELECT o.custid, c.name, MAX(o.payment)
  FROM orders AS o, customers AS c
  WHERE o.custid = c.custid
  GROUP BY o.custid;

Чтобы запрос был допустимым, имястолбец должен быть опущен в списке выбора или назван в предложении GROUP BY.

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

Причина, по которой этот пункт существует, является действительной и может сэкономить некоторое время, рассмотрим следующий запрос:

SELECT t.team_id, t.team_name, COUNT(*) AS Players
FROM teams AS t
    LEFT JOIN Players AS p
        ON p.team_id = t.team_id
GROUP BY t.team_id;

Здесь мы можем включить team_name в список выбора дажехотя он не входит в группу, но мы можем сделать это безопасно, поскольку team_id является первичным ключом, поэтому было бы невозможно иметь два разных значения team_name для одного team_id.

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

Вы можете получить отдельный список игроков и команд, используя DISTINCT:

SELECT DISTINCT t.team_name, P.player_name 
FROM teams AS t
    INNER JOIN Players AS p
        ON p.team_id = t.team_id;

Это по сути хак, и хотя он удаляет дублирующиеся записи, он не решает основную проблему, дублирующих записей ипотенциально неоптимальная структура данных.

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

Возможно, вам следует использовать соединительные таблицы для игроков и игр, т.е.ваши основные столы

Team (team_id, team_name, team_logo etc)
Game (game_id, game_name, etc)
Player (player_id, player_name, player_email, player_mobile etc)

Затем таблицы, чтобы связать их

Team_Game (team_id, game_id)
Team_Player (team_id, player_id)

Это позволяет одному игроку играть за несколько команд или одной команде за участие в нескольких событиях.

0 голосов
/ 06 июня 2019
Select t.team_id , p.player_name from player p
JOIN teams t 
ON t.team_id = p.team_id
Where t.game_id = 35 AND p.player_name IS NOT NULL AND p.player_name <> ''
GROUP BY(t.team_name)
```

You should do a unique constraint on the team_name column, this way you are not allowing duplicate teams

Ps. I did not test the query but it should work
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...