Что вернет SQL-запрос с inner join без условий, с left join и с full join
Что проверяют
Знаете ли вы, чем типы соединений отличаются по составу строк и по появлению NULL, и понимаете ли, что происходит с количеством строк. Для бэкендера на Go это ещё и вопрос про database/sql: форма результата определяет, во что вообще можно просканировать строку.
Как отвечать
Разбирайте по частям.
INNER JOINбезONв стандарте и в большинстве СУБД это синтаксическая ошибка. Декартово произведение пишется честно:CROSS JOINилиON true, результат это каждая строка слева со всеми строками справа. В MySQL соединение без условия разрешено и равноCROSS JOIN, в PostgreSQL нет.LEFT JOINотдаёт все строки левой таблицы плюс совпавшие справа, а где совпадения нет, колонки правой приходят NULL. Строк не меньше, чем в левой таблице, и больше, если справа на один ключ несколько строк.FULL JOINдобавляет ещё и несовпавшие строки правой таблицы, NULL появляется с обеих сторон. В MySQL его нет, эмулируют объединениемLEFTиRIGHTчерезUNION.
Дальше скажите сами про главную практическую деталь: условие по правой таблице в WHERE превращает внешнее соединение во внутреннее, потому что NULL не проходит проверку. Такому условию место в ON:
select u.id, o.id
from users u
left join orders o on o.user_id = u.id and o.status = 'paid';И про Go: после внешнего соединения колонки правой таблицы становятся nullable, поэтому rows.Scan в string или int64 падает на конвертации NULL. Нужны sql.NullString, указатель или coalesce прямо в запросе.
Где спотыкаются
Пишут LEFT JOIN без ON и ждут «все строки левой таблицы». Без условия запрос либо не соберётся, либо вернёт произведение, и это разные вещи.
Фильтруют правую таблицу в WHERE и удивляются, что строки без пары пропали. Единственное исключение это осознанный антиджойн по IS NULL.
Забывают, что соединение размножает строки: после LEFT JOIN с одним ко многим count и суммы по левой таблице считаются неверно, нужна агрегация в подзапросе.