Что происходит при LEFT JOIN, если в правой таблице нет соответствующих значений
Что проверяют
Понимаете ли вы семантику внешнего соединения и, раз речь про Go, что произойдёт при чтении такого результата в типы языка. На бэкенде это ежедневная задача, и обе части одинаково важны.
Как отвечать
LEFT JOIN возвращает все строки левой таблицы. Там, где справа совпадения нет, все колонки правой таблицы заполняются NULL. Меньше строк не станет, а больше может: одна левая строка с несколькими подходящими справа даст несколько строк результата.
Теперь про Go: NULL не ложится в string или int64, драйвер вернёт ошибку преобразования. Варианты три, и выбирают по смыслу:
var name sql.NullString
if err := rows.Scan(&o.ID, &name); err != nil { return err }
// name.Valid == false, если пары не нашлосьЛибо указатель *string, либо снять вопрос в запросе через COALESCE(c.name, ''). Последнее годится, только если вам не нужно различать «клиента нет» и «имя пустое».
Полезно добавить, что на внешнем соединении строится поиск сирот:
SELECT o.id FROM orders o
LEFT JOIN customers c ON c.id = o.customer_id
WHERE c.id IS NULLГде спотыкаются
Переносят условие по правой таблице в WHERE. Проверка вида c.status = 'active' отбрасывает строки, где справа пусто, и внешнее соединение молча превращается во внутреннее. Условие на правую таблицу остаётся в ON, в WHERE остаётся только IS NULL для поиска сирот.
Сканируют в обычные типы, потому что на тестовых данных пара находится всегда. Первая же строка без пары роняет обработчик на проде, и ошибку легко не заметить, если возврат rows.Err() не проверяется.
Считают, что внешнее соединение не размножает строки. При связи один ко многим счётчик по левой таблице завышается, и агрегат приходится считать подзапросом или через COUNT(DISTINCT ...).