Какие способы объединения двух датасетов в SQL существуют?
Что проверяют
Понимаете ли вы разницу между соединением, которое добавляет к строкам столбцы, и объединением наборов, которое складывает строки. Для C#-разработчика следом почти всегда идёт вопрос, как то же выглядит в LINQ и во что это переводит EF Core.
Как отвечать
Две группы операций:
INNER JOIN: только строки, у которых есть пара в обеих таблицах;LEFT JOIN: все строки левой таблицы, у несовпавших правые столбцыNULL.RIGHT JOINзеркален, его обычно переписывают в левый;FULL JOIN: все строки обеих таблиц, недостающая сторона заполняетсяNULL. Удобен для сверки двух выгрузок;CROSS JOIN: декартово произведение, например все товары на все даты;CROSS APPLYиOUTER APPLY: в SQL Server соединение с подзапросом, зависящим от текущей строки, например три последних заказа каждого клиента. В PostgreSQL то же делаетLATERAL;UNION ALL: склеивает результаты запросов с одинаковым числом совместимых по типу столбцов, имена берутся из первого;UNION: то же с удалением дублей, то есть с сортировкой или хэшированием;INTERSECTиEXCEPT: пересечение и разность наборов.
В LINQ join ... on ... equals даёт внутреннее соединение. Левое долго писали через GroupJoin, SelectMany и DefaultIfEmpty(), в .NET 10 появились операторы LeftJoin и RightJoin, и EF Core 10 их транслирует. Concat превращается в UNION ALL, Union в UNION, Intersect и Except в одноимённые операторы. Итоговый SQL проверяйте через ToQueryString() или логирование.
Где спотыкаются
Пишут LEFT JOIN, а условие на правую таблицу ставят в WHERE. Строки с NULL отсеиваются, и соединение молча становится внутренним. Такое условие переносят в ON.
Не учитывают кратность: если у ключа несколько совпадений справа, строки левой таблицы размножаются, и SUM даёт завышенный итог.
Пишут UNION по привычке там, где дублей быть не может. Лишняя дедупликация стоит сортировки всего результата, UNION ALL дешевле.