MySQL - нужна помощь в подсчете идентификаторов, которые соответствуют определенным в других таблицах - PullRequest
0 голосов
/ 20 июля 2009

У меня есть таблица с именем players, затем другие таблицы с именем tries, conversions, penalties, dropgoals.

Мне нужно получить player_id из players, а затем посчитать следующее:

  • количество попыток для player_id в tries
  • количество преобразований для player_id в conversions
  • количество штрафов за player_id в penalties
  • количество дропголов для player_id в dropgoals

И все это должно произойти за один раз, так как на каждую игру приходится около пятнадцати игроков, сайт относится к регби.

Я пробовал следующее, который работает:

SELECT players.player_id, players.number, CASE WHEN (COUNT(tries.player_id) = 0) THEN ' ' ELSE COUNT(tries.player_id) END AS nrTries FROM players LEFT JOIN tries ON players.player_id = tries.player_id WHERE players.team_id IS NULL GROUP BY players.player_id ORDER BY players.number

Он выбирает всех игроков из таблицы players и считает их попытки, но как только я изменяю его на следующее, я получаю сообщение об ошибке:

SELECT players.player_id, players.number, player.name, CASE WHEN (COUNT(tries.player_id) = 0) THEN ' ' ELSE COUNT(tries.player_id) END AS nrTries FROM players, player LEFT JOIN tries ON players.player_id = tries.player_id WHERE players.player_id = player.player_id AND players.team_id IS NULL GROUP BY players.player_id ORDER BY players.number

Выдает следующую ошибку:

Unknown column 'players.player_id' in 'on clause'

Может кто-нибудь помочь мне с этим, я боролся уже несколько дней?

Заранее спасибо

// редактировать:

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

Допустим, мой игрок набрал 1 пенальти и 3 дропгола, он выдает 3 пенальти и 3 дропгола, я не могу понять, в чем дело.

Вот мой запрос:

SELECT players.player_id, players.number, player.name, player.surname,
CASE WHEN (COUNT(tries.player_id) = 0) THEN '& nbsp;' ELSE COUNT(tries.player_id) END AS nrTries,
CASE WHEN (COUNT(conversions.player_id) = 0) THEN '& nbsp;' ELSE COUNT(conversions.player_id) END AS nrConversions,
CASE WHEN (COUNT(dropgoals.player_id) = 0) THEN '& nbsp;' ELSE COUNT(dropgoals.player_id) END AS nrDropgoals,
CASE WHEN (COUNT(penalties.player_id) = 0) THEN '& nbsp;' ELSE COUNT(penalties.player_id) END AS nrPenalties
FROM players
LEFT JOIN tries ON players.player_id = tries.player_id AND tries.game_id = '$game_id'
LEFT JOIN conversions ON players.player_id = conversions.player_id AND conversions.game_id = '$game_id'
LEFT JOIN dropgoals ON players.player_id = dropgoals.player_id AND dropgoals.game_id = '$game_id'
LEFT JOIN penalties ON players.player_id = penalties.player_id AND penalties.game_id = '$game_id'
LEFT JOIN player ON players.player_id = player.player_id
WHERE players.player_id = player.player_id AND players.team_id IS NULL AND players.game_id = '$game_id'
GROUP BY players.player_id ORDER BY players.number

Обратите внимание: $ game_id - это переменная PHP.
Также: Я добавил пробел между & и nbsp; в противном случае он не передается на SO.

Может кто-нибудь указать мне правильное направление?

Ответы [ 3 ]

3 голосов
/ 20 июля 2009

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

SELECT player_id, tries, conversions, penalties, dropgoals
FROM players p
LEFT JOIN tries t ON t.player_id = p.player_id
LEFT JOIN conversions c ON c.player_id = p.player_id
LEFT JOIN penalties e ON e.player_id = p.player_id
LEFT JOIN dropgoals d ON d.player_id = p.player_id

Это можно переформулировать как:

SELECT player_id
(SELECT tries FROM tries WHERE player_id = p.player_id) tries,
(SELECT conversions FROM conversions WHERE player_id = p.player_id) conversions,
(SELECT penalties FROM penalties WHERE player_id = p.player_id) penalties,
(SELECT dropgoals FROM dropgoals WHERE player_id = p.player_id) dropgoals
FROM players p

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

SELECT player_id
(SELECT SUM(tries) FROM tries WHERE player_id = p.player_id) tries,
(SELECT SUM(conversions) FROM conversions WHERE player_id = p.player_id) conversions,
(SELECT SUM(penalties) FROM penalties WHERE player_id = p.player_id) penalties,
(SELECT SUM(dropgoals) FROM dropgoals WHERE player_id = p.player_id) dropgoals
FROM players p

Любое из вышеперечисленного может использовать IFNULL () или аналогичные функции для возврата 0 вместо NULL, если это необходимо.

1 голос
/ 21 июля 2009

Я немного запутался, почему вы заявили, что у Cletus было правильное решение, и продолжали не использовать его при обновлении исходного вопроса. Тем не менее, решение Cletus слегка отключено, вам нужно COUNT (), а не SUM (). Попробуйте следующее:

SELECT players.player_id,
(SELECT COUNT(*) FROM tries WHERE player_id = players.player_id) tries,
(SELECT COUNT(*) FROM penalties WHERE player_id = players.player_id) penalties
FROM players;

Это вернет 0 вместо того, чтобы & nbsp я бы порекомендовал обработать это в коде вашего приложения. Вы можете добавить в CASE беспорядок, если вы действительно хотите получить & nbsp от mysql.

0 голосов
/ 20 июля 2009

Почему второй запрос ссылается на «игрок»? Я не вижу, чтобы вы упоминали такую ​​таблицу где-либо еще ... ("ОТ игроков, игрок") Просто убедитесь, что это преднамеренно.

Может быть полезно избегать смешивания явных объединений (например, «LEFT JOIN») с неявными объединениями (например, «FROM Players, Player»), чтобы сохранить вашу структуру согласованной.

...