Что такое FULL OUTER JOIN, как он работает и чем отличается от других видов JOIN?

Ответ

FULL OUTER JOIN (в некоторых СУБД просто FULL JOIN) — это тип объединения таблиц, который возвращает все строки из обеих таблиц.

Принцип работы:

  1. Возвращаются все строки, для которых выполняется условие объединения (как в INNER JOIN).
  2. Возвращаются все строки из левой таблицы, для которых не нашлось совпадений в правой (как в LEFT JOIN), при этом столбцы правой таблицы заполняются NULL.
  3. Возвращаются все строки из правой таблицы, для которых не нашлось совпадений в левой (как в RIGHT JOIN), при этом столбцы левой таблицы заполняются NULL.

Пример SQL-запроса:

SELECT c.name, o.order_id
FROM customers c
FULL OUTER JOIN orders o ON c.id = o.customer_id;

Результат будет содержать:

  • Клиентов, у которых есть заказы.
  • Клиентов, у которых нет заказов (поле order_id будет NULL).
  • Заказы, у которых по какой-то причине нет связанного клиента (поле name будет NULL).

Применение в Go:

В Go вы просто пишете SQL-запрос как строку и выполняете его с помощью пакета database/sql. Go не интерпретирует сам SQL, а отправляет его в СУБД. Ключевой момент — правильная обработка NULL значений, которые вернет запрос. Для этого в Go используются специальные типы из пакета database/sql, такие как sql.NullString, sql.NullInt64 и т.д.

var customerName sql.NullString
var orderID sql.NullInt64

err := row.Scan(&customerName, &orderID)
// ...

if customerName.Valid {
    // Используем customerName.String
}
// Если !customerName.Valid, значит, в базе было NULL

Ответ 18+ 🔞

Давай разберём эту штуку, FULL OUTER JOIN, а то народ иногда в ступор впадает, как будто им хуй с горы показали.

Представь, что у тебя есть две таблицы. Одна — про клиентов, другая — про заказы. И вот ты такой царь-батюшка, хочешь увидеть ВСЁ И СРАЗУ. Всех клиентов, все заказы, и чтобы те, кто совпали, были вместе, а кто нет — так и висели по отдельности, как манда с ушами.

Вот как это работает, ёпта:

  1. Совпадения (как INNER JOIN): Берутся все парочки, где клиенту в заказе повезло и он нашёлся. Красота.
  2. Левые сироты (как LEFT JOIN): Берутся все клиенты, которые такие одинокие, что заказа у них нихуя нет. На месте заказа будет пустота, NULL.
  3. Правые сироты (как RIGHT JOIN): Берутся все заказы-подкидыши, которые непонятно от какого клиента припёрлись. На месте имени клиента — та же пустота, NULL.

Вот тебе пример запроса, смотри:

SELECT c.name, o.order_id
FROM customers c
FULL OUTER JOIN orders o ON c.id = o.customer_id;

Что в итоге вылезет? Да всё, блядь!

  • Вася (клиент) и его заказ №5.
  • Петя (клиент), который нихуя не заказывал, но мы его всё равно видим. Рядом с order_idNULL.
  • Заказ №42, который есть, а клиент на него записан какой-то левый, которого у нас в базе нет. Рядом с nameNULL.

А как это в Go применить?

А вот тут внимание, волнение ебать! Go сам SQL не жуёт, он его тупо отправляет в базу. Вся магия — в обработке ответа. Потому что эти самые NULL значения обычными string или int не прочитать, пидарас шерстяной! Надо использовать специальные обёртки.

Смотри, как это выглядит:

var customerName sql.NullString
var orderID sql.NullInt64

err := row.Scan(&customerName, &orderID)
// ...

if customerName.Valid {
    // Всё ок, имя есть, работаем с customerName.String
} else {
    // А тут customerName.Valid == false. Значит, в базе был NULL. Клиента нет, заказ-сирота.
}

Вот и весь секрет. FULL OUTER JOIN — это когда тебе похуй на логику связей, ты хочешь всю картину, со всеми дырками и нестыковками. Как жизнь, только в SQL.