В чем разница левого и правого join в SQL
Что проверяют
Понимаете ли вы, какие строки попадают в результат и откуда берутся NULL, а не только помните определение. Для C#-разработчика следом почти всегда спрашивают, как сделать левое соединение в LINQ и во что его переведёт EF Core.
Как отвечать
Суть в одном предложении: LEFT JOIN сохраняет все строки левой таблицы, RIGHT JOIN все строки правой, а недостающая сторона заполняется NULL. Дальше покажите, что это одна операция:
- симметрия:
A RIGHT JOIN Bдаёт те же строки, чтоB LEFT JOIN A, отличается только порядок колонок. Поэтому в коде обычно пишут толькоLEFT JOIN, так запрос читается от главной таблицы; - пример:
Customers LEFT JOIN Ordersвернёт и клиентов без заказов, у них поля заказа будутNULL. Найти таких клиентов можно условиемWHERE o.Id IS NULL; - размножение строк: при связи «один ко многим» клиент с тремя заказами даст три строки, это не дубли, а свойство соединения;
- поддержка: не все движки умеют
RIGHT JOIN, SQLite добавил его только в 2022 году.
Про C#: в LINQ левое соединение классически пишется через join ... into и DefaultIfEmpty() (или GroupJoin плюс SelectMany), EF Core переводит это в LEFT JOIN. В .NET 10 появились операторы LeftJoin и RightJoin, EF Core 10 их транслирует. Необязательную навигационную связь EF Core тоже превращает в LEFT JOIN сам.
Где спотыкаются
Ставят фильтр по правой таблице в WHERE, например WHERE o.Status = 'Paid'. Строки с NULL отсекаются, и левое соединение молча превращается во внутреннее. Условию по правой таблице место в ON.
Путают результат с объединением: «все строки обеих таблиц» это FULL OUTER JOIN, а не LEFT JOIN.
В C# забывают, что после левого соединения поля правой стороны могут быть null, и проецируют их в ненулевой int или DateTime. Итог: InvalidOperationException при материализации, нужен int? или явная проверка.