Объясните, как работают несколько left join?

Есть несколько таблиц.

Книги с полями id и name.
Жанры с полями id и name.
Оценки с полями userid rating и bookid
Жанры книг с полями bookid и genreid.

Результирующий запрос должен давать такую таблицу.

name | rating | urating | genrename |
Some | 8 | 5 | g1, g2, gn|

Но запрос:

SELECT 
b.name, 
AVG(br.rating) as rating, 
MAX(ubr.rating) as urating, 
GROUP_CONCAT(g.name) as genrename
FROM books b
LEFT JOIN book_rating br ON br.book_id = b.id
LEFT JOIN book_rating ubr ON ubr.book_id = b.id AND ubr.user_id = 1
LEFT JOIN book_genre bg ON bg.book_id = b.id
LEFT JOIN genre g ON g.id = bg.genre_id
WHERE b.id = 1
GROUP BY b.id


Выводит:

name | rating | urating | genrename |
Some | 8 | 5 | g1, g2, gn, g1, g2, gn.|

То есть в зависимости от переменных запроса, результат столбца genrename повторяется несколько раз.
Каким то образом присоединение таблицы рейтинг влияет на результат столбца genrename.

Я понимаю, что запрос можно написать по другому, но для меня стал неожиданным такой результат и я хочу понять, почему это так работает?

P.S. Прошу прощение за кривоватый текст. (пишу с телефона).
  • Вопрос задан
  • 3459 просмотров
Решения вопроса 1
WStanley
@WStanley
Back-end Developer
Доброго!
Оценок у одной книги может быть несколько, жанров как я понял тоже, вот строки и задваиваются, чтобы увидеть это просто уберите группиворку и выполните запрос. Это поможет понять что происходит. А лучше уберите группировку и по очереди джойните таблицы анализируя результат, все станет понятно.

Если на пальцах объяснять то к каждому id книги будут прикреплены все оценки этой книги
book | rating
---------------
 1   |    4
 1   |    5

Если вы джойните еще одну таблицу то картина будет примерно такой
book | rating | gename
----------------------
  1   |  4    |  g1
  1   |  4    |  g2
  1   |  5    |  g1
  1   |  5    |  g2

Соответственно после группировок у вас:
book | rating | gename
----------------------
  1   |  4.5    |  g1, g2, g1, g2

А чтоб решить проблему используйте GROUP_CONCAT_DISTINCT
Он исключит повторяющиеся значения
book | rating | gename
----------------------
  1   |  4.5    |  g1, g2

p.s. В любой непонятной ситуации убирай группировку
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы