#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-коде.