Соедините T2 с T1 на T2.x = T1.x, если есть совпадение, еще на T2.y = T1.y, если совпадения нет

#mysql #sql #join

Вопрос:

У меня есть 2 таблицы: Таблица событий, которая содержит команды и пользователей из тех команд, которые зарегистрированы для участия в мероприятии, и таблица команд, которая содержит все команды и их игроков (независимо от событий).

Я хотел бы присоединиться к командам на мероприятиях, где Teams.user_id = Events.user_id, а затем присоединиться к любым оставшимся строкам в командах, где Teams.team_id = События.team_id.

Так, например, эти 2 таблицы приведут к следующему результату

  ---------------------------------------      ------------------------- 
|                 Events                |    |          Teams          |
 ---------- --------- --------- --------      --------- --------- ----- 
| event_id | team_id | user_id |  foo   |    | team_id | user_id | bar |
 ---------- --------- --------- --------      --------- --------- ----- 
|    1     |    1    |    1    |   1    |    |    1    |    1    |  A  |
 ---------- --------- --------- --------      --------- --------- ----- 
|    1     |    1    |    2    |   0    |    |    1    |    2    |  A  |
 ---------- --------- --------- --------      --------- --------- ----- 
|    1     |    2    |   NULL  |  NULL  |    |    2    |    3    |  A  |
 ---------- --------- --------- --------      --------- --------- ----- 
|    1     |    3    |    5    |   0    |    |    2    |    4    |  B  |
 ---------- --------- --------- --------      --------- --------- ----- 
                                             |    3    |    5    |  A  |
                                              --------- --------- ----- 
                                             |    4    |    6    |  A  |
                                              --------- --------- ----- 
 
  --------------------------------------------- 
|               Expected Result               |
 ---------- --------- --------- -------- ----- 
| event_id | team_id | user_id |  foo   | bar |
 ---------- --------- --------- -------- ----- 
|    1     |    1    |    1    |   1    |  A  |
 ---------- --------- --------- -------- ----- 
|    1     |    1    |    2    |   0    |  A  |
 ---------- --------- --------- -------- ----- 
|    1     |    2    |    3    |  NULL  |  A  |
 ---------- --------- --------- -------- ----- 
|    1     |    2    |    4    |  NULL  |  B  |
 ---------- --------- --------- -------- ----- 
|    1     |    3    |    5    |   0    |  A  |
 ---------- --------- --------- -------- ----- 
 

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

 SELECT Events.*, Teams.*
FROM Events
RIGHT JOIN Teams ON CASE
  WHEN Teams.user_id = Events.user_id
  THEN Teams.user_id = Events.user_id
  ELSE Teams.team_id = Events.team_id
END
WHERE Events.event_id = (/* subquery that yields event_id */)

/* or for join */

RIGHT JOIN Teams ON
  (Teams.user_id = Events.user_id AND Teams.team_id = Events.team_id)
  OR Teams.team_id = Events.team_id
/* also */
RIGHT JOIN Teams ON
  (Events.user_id IS NOT NULL AND Teams.user_id = Events.user_id)
  OR (Events.user_id IS NULL AND Teams.team_id = Events.team_id)`
 

Изменить: Скорректированная таблица, учитывающая присоединение повторяющихся пользователей с помощью чего-то подобного LEFT JOIN Teams ON Teams.user_id = Events.user_id OR Teams.team_id = Events.team_id .

Комментарии:

1. Большинству людей main table left join optional data гораздо легче понять, чем optional data right join main table .

2. попробуйте ((Команды.Идентификатор пользователя = События.идентификатор пользователя И Команды.Идентификатор команды = События.идентификатор команды) ИЛИ (Команды.идентификатор пользователя равен нулю, А Команды.Идентификатор команды = События.идентификатор команды))

3. @Emanuele Я пробовал, но Teams.user_id на самом деле никогда не будет равен нулю, так что это просто дает мне результаты первой части, Teams.user_id = Events.user_id AND Teams.team_id = Events.team_id

4. Я использовал Teams.идентификатор пользователя равен нулю, а не Teams.team_id

5. @jarlh Проблема в том, что я заранее не знаю идентификаторы команд, которые мне нужны, только идентификатор события в Событиях, поэтому мне приходится присоединяться к командам на Мероприятиях.

Ответ №1:

Дайте мне знать, работает ли это для вашего полного набора данных. Он работал с вашими образцами данных, предоставленными, как показано в скрипке базы данных ниже:

Схема (MySQL v8.0)

 CREATE TABLE events (
  `event_id` INTEGER,
  `team_id` INTEGER,
  `user_id` VARCHAR(4),
  `foo` VARCHAR(4)
);

INSERT INTO events
  (`event_id`, `team_id`, `user_id`, `foo`)
VALUES
  ('1', '1', '1', '1'),
  ('1', '2', 'NULL', 'NULL'),
  ('1', '3', '5', '0');
  
  

CREATE TABLE teams (
  `team_id` INTEGER,
  `user_id` INTEGER,
  `bar` VARCHAR(1)
);

INSERT INTO teams
  (`team_id`, `user_id`, `bar`)
VALUES
  ('1', '1', 'A'),
  ('1', '2', 'A'),
  ('2', '3', 'A'),
  ('2', '4', 'B'),
  ('3', '5', 'A'),
  ('4', '6', 'A');
 

Запрос № 1

 SELECT
    e.event_id,
    e.team_id,
    t.user_id,
    CASE
        WHEN e.user_id <> t.user_id THEN NULL
        ELSE e.foo
    END as foo,
    t.bar
FROM
   events e
INNER JOIN
   teams t ON e.user_id = t.user_id OR t.team_id = e.team_id;
 
идентификатор события team_id идентификатор пользователя фу бар
1 1 1 1 A
1 1 2 нулевой A
1 2 3 нулевой A
1 2 4 нулевой B
1 3 5 0 A

Просмотр на скрипке БД

Комментарии:

1. Извините, я знаю, что опоздал на это, я отвлекся на другие дела и, наконец, просто вернулся к этому. Проблема здесь в том, что это приводит к объединению команды из таблицы Команд для каждого пользователя в этой команде в таблице событий. Например, если вы также добавите пользователя 2 из команды 1 в таблицу событий, то запрос на присоединение приведет к тому, что команда 1 будет присоединена дважды , по одному разу для каждого пользователя из этой команды. И при использовании с GROUP_CONCAT (что я и собираюсь сделать), вы не можете использовать что-то подобное GROUP BY t.user_id . Возможно, мне просто придется отказаться от использования GROUP_CONCAT и сделать это в своем JS-коде.