Как посчитать количество разных элементов в SQL - PullRequest
3 голосов
/ 23 января 2009

Структура базы данных:

Clubs: ID, ClubName
Teams: ID, TeamName, ClubID
Players: ID, Name
Registrations: PlayerID, TeamID, Start_date, End_date, SeasonID

Клубы владеют несколькими командами. Игроки могут зарегистрироваться в нескольких командах (внутри одного клуба или в другом клубе) в течение одного года. Я должен сгенерировать запрос, чтобы перечислить всех игроков, которые были зарегистрированы в РАЗНЫХ КЛУБАХ в течение одного сезона. Так что, если игрок поменял команды, принадлежавшие одному и тому же клубу, это не засчитывается.

Мои попытки пока:

SELECT
c.short_name,
p.surname,
r.start_date,
r.end_date,
(select count(r2.id) from ejl_registration as r2
    where r2.player_id=r.player_id and r2.season=r.season) as counter
FROM
ejl_registration AS r
left Join ejl_players AS p ON p.id = r.player_id
left Join ejl_teams AS t ON r.team_id = t.id
left Join ejl_clubs AS c ON t.club_id = c.id
WHERE
r.season =  '2008'
having counter >1

Я не могу понять, как считать и показывать только разные клубы ... (уже слишком поздно для ясного мышления). Я использую MySQL.

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

Ответы [ 3 ]

4 голосов
/ 23 января 2009

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

SELECT p.surname, r.start_date, r.end_date, COUNT(DISTINCT c.id) AS counter
FROM ejl_players p
 JOIN ejl_registration r ON (r.player_id = p.id)
 JOIN ejl_teams t ON (r.team_id = t.id)
 JOIN ejl_clubs c ON (t.club_id = c.id)
WHERE r.season = '2008'
GROUP BY p.id
HAVING counter > 1;

Обратите внимание, что, поскольку вы используете MySQL, вы можете быть довольно гибкими в отношении столбцов в списке выбора, не соответствующих столбцам в предложении GROUP BY. Другие бренды РСУБД более строго относятся к правилу единой стоимости.

Нет причин использовать левое соединение, как в вашем примере.


Хорошо, вот первая версия запроса:

У вас есть цепочка отношений, подобная следующей:

club1 <-- team1 <-- reg1 --> player <-- reg2 --> team2 --> club2

Так что club1 не должен совпадать с club2.

SELECT p.surname,
  CONCAT_WS(',', GROUP_CONCAT(DISTINCT t1.team_name), 
    GROUP_CONCAT(DISTINCT t2.team_name)) AS teams,
  CONCAT_WS(',', GROUP_CONCAT(DISTINCT c1.short_name), 
    GROUP_CONCAT(DISTINCT c2.short_name)) AS clubs
FROM ejl_players p
 -- Find a club where this player is registered
 JOIN ejl_registration r1 ON (r1.player_id = p.id)
 JOIN ejl_teams t1 ON (r1.team_id = t1.id)
 JOIN ejl_clubs c1 ON (t1.club_id = c1.id)
 -- Now find another club where this player is registered in the same season
 JOIN ejl_registration r2 ON (r2.player_id = p.id AND r1.season = r2.season)
 JOIN ejl_teams t2 ON (r2.team_id = t2.id)
 JOIN ejl_clubs c2 ON (t2.club_id = c2.id)
-- But the two clubs must not be the same (use < to prevent duplicates)
WHERE c1.id < c2.id
GROUP BY p.id;
0 голосов
/ 23 января 2009
SELECT p.Name, x.PlayerID, x.SeasonID
  FROM (SELECT DISTINCT r.PlayerID, r.SeasonID, t.ClubID
          FROM Registrations r
          JOIN Teams t ON t.ID = r.TeamID) x
  JOIN Players p ON p.ID = x.PlayerID
 GROUP BY p.rName, x.PlayerID, x.SeasonID
HAVING COUNT(*) > 1
0 голосов
/ 23 января 2009

Вот список игроков за один сезон.

SELECT sub.PlayerId
FROM
(
  SELECT
    r.PlayerId,
    (SELECT t.ClubID FROM Teams t WHERE r.TeamID = t.ID) as ClubID
  FROM Registrations r
  WHERE r.Season = '2008'
) as sub
GROUP BY PlayerId
HAVING COUNT(DISTINCT sub.ClubID) > 1

Вот список игроков и сезонов для всех сезонов.

SELECT PlayerId, Season
FROM
(
SELECT
  r.PlayerId,
  r.Season,
  (SELECT t.ClubID FROM Teams t WHERE r.TeamID = t.ID) as ClubID
FROM Registrations r
) as sub
GROUP BY PlayerId, Season
HAVING COUNT(DISTINCT sub.ClubID) > 1

Кстати, это работает в MS SQL.

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