2013-07-31 4 views
0

В этом запросе я должен указать пару игроков с их идентификатором playerID и playerName, которые играют за ту же команду. Если игрок играет за 3 команды, другой должен играть за точные 3 команды. Не меньше, не больше. Если два игрока в настоящее время не играют ни за какую команду, они также должны быть включены. Запрос должен возвращать (playerID1, playername1, playerID2, playerName2) без повторения, например, если информация игрока 1 находится перед игроком 2, не должно быть другого кортежа с игроком 2 информация, поступающая перед игроком 1.Сложный SQL-запрос, включающий несколько таблиц

Например, если игрок Игра для янки и redsox, а игрок b играет для янки, Red Sox и Dodgers, я не должен их получать. Они оба должны играть за янки, а Red Sox и ни с кем другим. Прямо сейчас этот запрос находит ответ, если игроки играют за одну и ту же команду.

player(playerID: integer, playerName: string) 
team(teamID: integer, teamName: string, sport: string) 
plays(playerID: integer, teamID: integer) 

Сейчас запрос у меня есть

SELECT p1.playerID, p1.playerName, p2.playerID, p2.playerName 
FROM player p1, player p2, plays 
WHERE p1.teamID = p2.teamID AND teamID in..... 

я застрял на том, как подойти к нему после этого. Любые подсказки о том, как подойти к этой проблеме. Спасибо за ваше время.

+0

, какую базу данных мы работаем с? – hd1

+0

Извините, у меня есть локальная база данных, которую я использую, но я не знаю, как ее поместить. – user2632133

+0

Какой сервер баз данных? Версия также может быть релевантной – hd1

ответ

2

Я думаю, что самый простой подход - объединить команды и просто присоединиться к результатам. Postgres обеспечивает функцию string_agg() агрегировать строки:

select p1.playerId, p1.playerName, p2.playerId, p2.playerName 
from (select p.playerId, string_agg(cast(p.TeamId as varchar(255)), ',' order by TeamId) as teams, 
      pp.PlayerName 
     from plays p join 
      players pp 
      on p.playerId = pp.playerId 
     group by p.playerId 
    ) p1 join 
    (select p.playerId, string_agg(cast(p.TeamId as varchar(255)), ',' order by TeamId) as teams, 
      pp.PlayerName 
     from plays p join 
      players pp 
      on p.playerId = pp.playerId 
     group by p.playerId 
    ) p2 
    on p1.playerid < p2.playerid and p1.teams = p2.teams; 

EDIT:

Вы можете сделать это без string_agg. Идея состоит в том, чтобы начать со списка всех возможных комбинаций игроков.

Затем присоединяйтесь к командам для первого игрока, используя left outer join. И присоединитесь к командам для второго, используя full outer join и сопоставив команду и имя водителя. Причина, по которой нужно в таблице драйвера должен быть уверен, что идентификатор/имя не затеряться в полном внешнем объединении:

select driver.playerid1, driver.playerid2 
from (select p1.playerId as playerId1, p1.playerName as playerName1, 
      p2.playerId as playerId2, p1.playerName as playerName2 
     from players p1 cross join 
      players p2 
     where p1.playerId < p2.playerId 
    ) driver left outer join 
    plays p1 
    on p1.playerId = driver.playerId full outer join 
    plays p2 
    on p2.playerId = driver.playerId and 
     p2.teamid = p1.teamid 
group by driver.playerid1, driver.playerid2 
having count(p1.playerid) = count(*) and 
     count(p2.playerid) = count(*); 

Это объединение двух игроков команды идентификатору (с заказом поэтому пара только получает считается один раз). Затем он говорит, что есть совпадение, когда все строки для двух игроков имеют значения, отличные от NULL. Это, возможно, более ясно, с эквивалентным having пункта:

having sum(case when p1.playerid is null then 1 else 0 end) = 0 and 
     sum(case when p2.playerid is null then 1 else 0 end) = 0; 

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

+0

Есть ли способ сделать это без использования string-agg. Извините, я не знаком с этой концепцией. – user2632133

+0

Большое спасибо, теперь это имеет смысл. только вопрос. Что вы подразумеваете под окончательным объединением? – user2632133

+0

На самом деле это дает мне игроков, которые играют за ту же команду, а не в playera, которые играют точно в те же команды. Например, если игрок A играет для янки и redsox, а игрок b играет для янки, Red Sox и Dodgers, я не должен их получать. Они оба должны играть за янки, а Red Sox и ни с кем другим. Прямо сейчас этот запрос находит ответ, если игроки играют за одну и ту же команду. – user2632133

0

Это адаптация my answer к вашему previous question.

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

    SELECT p1.playerID, p1.playerName, p2.playerID, p2.playerName 
    FROM player p1 
    INNER JOIN player p2 ON p1.playerID < p2.playerID 
    
  2. Вычесть команду второго игрока набор от первого игрока и проверьте, нет строки в результате:

    NOT EXISTS (
        SELECT teamID 
        FROM plays 
        WHERE playerID = p1.playerID 
    
        EXCEPT 
    
        SELECT teamID 
        FROM plays 
        WHERE playerID = p2.playerID 
    ) 
    
  3. своп наборы, вычитать и проверить еще раз:

    NOT EXISTS (
        SELECT teamID 
        FROM plays 
        WHERE playerID = p2.playerID 
    
        EXCEPT 
    
        SELECT teamID 
        FROM plays 
        WHERE playerID = p1.playerID 
    ) 
    
  4. Наконец, применяются оба условия к результату треугольных присоединиться Шаг 1.

    SELECT p1.playerID, p1.playerName, p2.playerID, p2.playerName 
    FROM player p1 
    INNER JOIN player p2 ON p1.playerID < p2.playerID 
    WHERE 
        NOT EXISTS (
         SELECT teamID 
         FROM plays 
         WHERE playerID = p1.playerID 
    
         EXCEPT 
    
         SELECT teamID 
         FROM plays 
         WHERE playerID = p2.playerID 
        ) 
    AND 
        NOT EXISTS (
         SELECT teamID 
         FROM plays 
         WHERE playerID = p2.playerID 
    
         EXCEPT 
    
         SELECT teamID 
         FROM plays 
         WHERE playerID = p1.playerID 
        ) 
    ; 
    
Смежные вопросы