Выбор нескольких значений таблицы с двойным соединением

У меня есть запрос, который выбирает значения из разных таблиц через JOIN. Но я думаю, что у меня сейчас проблема, потому что одну таблицу нужно снова объединить с другим именем, но почему-то это не работает.

Пример на основе структуры социальной сети:

Таблица «пользователи»:

+--------+-----------+
| userid | username  | 
+--------------------|
| 1      | userOne   | 
| 2      | userTwo   | 
| 3      | userThree | 
+--------+-----------+

Таблица "посты":

+--------+---------+-------------------------------+
| postid | userid  | text                          |
+--------------------------------------------------|
| 102    | 1       | "Haha i'm User one"           |
| 103    | 1       | "And User one is the best"    |
| 104    | 3       | "I'm having fun with user two"|
+--------+---------+-------------------------------+

Таблица "пользовательские теги":

+--------+---------------+
| postid | tagged_userid | 
+------------------------|
| 104    | 2             | 
+--------+---------------+

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

SELECT posts.postid,
   posts.userid,
   posts.text, 
   users.username,
   IFNULL(GROUP_CONCAT(DISTINCT usertags.tagged_userid SEPARATOR ','), NULL) as 
taggedusers_id,
   IFNULL(GROUP_CONCAT(DISTINCT taggedusers.fullname SEPARATOR ','), NULL) as 
taggedusers_name, 
     FROM posts
JOIN users ON posts.userid = users.userid
LEFT JOIN usertags ON posts.postid = usertags.postid
LEFT JOIN users as taggedusers ON usertags.tagged_userid = users.userid
 GROUP BY posts.postid
 ORDER BY posts.postid DESC

И вот результат, который я получаю:

+--------+---------+---------------------------------------------------------------------+
| postid | userid  | text                          | username           | taggedusers_id |
+-----------------------------------------------------------------------|----------------|
| 102    | 1       | "Haha i'm User one"           | userOne            | NULL           |
| 103    | 1       | "And User one is the best"    | userOne            | NULL           |
| 104    | 3       | "I'm having fun with user two"| userThree          | 2
+--------+---------+-------------------------------+--------------------+----------------+

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

+---------------+-------------------+
| taggeduser_id | taggeduser_name   | 
+-----------------------------------|
| 2             | userTwo           | 
| 2,3           | userTwo,userThree | 
| NULL          | NULL              | 
+---------------+-------------------+

Итак, как это возможно? Нужно ли мне делать множественный оператор SELECT? Я уже пробовал это, но у меня тоже не получилось :/ Буду рад помощи!


person Olli    schedule 25.10.2017    source источник
comment
Ваши образцы данных не соответствуют желаемому результату, а также схема не завершена, у вас отсутствуют столбцы, используемые в запросе.   -  person Juan Carlos Oropeza    schedule 25.10.2017
comment
Не имеет отношения к делу, в чем смысл IFNULL(***, NULL)? По сути, вы говорите, что если это NULL, установите его на NULL. Кажется излишним, если только я не упускаю выгоду.   -  person kchason    schedule 25.10.2017
comment
@KeithChason, вероятно, имел в виду IFNULL(***, '')   -  person Juan Carlos Oropeza    schedule 25.10.2017


Ответы (1)


Проблема в том, что вы снова ссылаетесь на users без псевдонима. Поскольку users уже неявно является INNER JOIN (см. этот вопрос What является поведением MySQL JOIN по умолчанию, ВНУТРЕННИМ или ВНЕШНИМ?), поэтому таблица taggedusers должна будет соответствовать условиям, согласно которым автор совпадает с помеченным идентификатором пользователя.

SELECT posts.postid,
   posts.userid,
   posts.text, 
   users.username,
   IFNULL(GROUP_CONCAT(DISTINCT usertags.tagged_userid SEPARATOR ','), NULL) as 
taggedusers_id,
   IFNULL(GROUP_CONCAT(DISTINCT taggedusers.fullname SEPARATOR ','), NULL) as 
taggedusers_name, 
FROM 
    posts
JOIN 
    users 
    ON posts.userid = users.userid
LEFT JOIN 
    usertags 
    ON posts.postid = usertags.postid
LEFT JOIN 
    users as taggedusers 
    ON usertags.tagged_userid = taggedusers.userid -- this is (I assume) what you meant
    -- ON usertags.tagged_userid = users.userid -- this is your problem
GROUP BY 
    posts.postid
ORDER BY 
    posts.postid DESC

Один из способов избежать этого — всегда использовать псевдонимы для таблиц; в этом случае вы могли бы использовать псевдоним users как «автор» или что-то в этом роде.

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

person kchason    schedule 25.10.2017
comment
Спасибо! Вы сэкономили мне много часов, осознав это - person Olli; 25.10.2017