FULL OUTER JOIN ба CROSS JOIN
Join-уудын ангиллаа дуусгая. FULL OUTER JOIN нь хоёр хүснэгтийн бүгдийг нэгэн зэрэг харуулдаг — аль нэг талд таарахгүй байсан ч. CROSS JOIN нь хоёр хүснэгтийн бүх мөрийн бүх хослолыг үүсгэдэг. Хоёулаа тусгай тохиолдолд маш хэрэгтэй.
FULL OUTER JOIN — хоёр талын бүгдийг хадгална
LEFT JOIN зүүнийг, RIGHT JOIN баруунийг хамгаалдаг байсан бол FULL OUTER JOIN хоёуланг хамгаалдаг. Аль хүснэгтэд таарахгүй байсан ч бичлэг үр дүнд орно — таарахгүй тал NULL болно.
SELECT
a.нэр AS зохиогч,
p.гарчиг AS нийтлэл
FROM authors AS a
FULL OUTER JOIN posts AS p ON p.author_id = a.id;
Хэрэв authors-т Ганбаяр нийтлэлгүй, posts-т зохиогчгүй нийтлэл байвал:
зохиогч | нийтлэл
-------------+----------------------
Болд | SQL суурь
Болд | JOIN тайлбар
Сарнай | Index гэж юу вэ
Ганбаяр | NULL ← зохиогч байгаа, нийтлэл байхгүй
NULL | Эзэнгүй нийтлэл ← нийтлэл байгаа, зохиогч байхгүй
FULL OUTER JOIN-ны хэрэглээ
Хоёр өгөгдлийн эх үүсвэрийн ялгааг харах — жишээ нь хуучин ба шинэ системийн мэдээллийг харьцуулах:
-- Хуучин ба шинэ хэрэглэгчийн жагсаалтыг харьцуулах
SELECT
old_users.имэйл AS хуучин_систем,
new_users.имэйл AS шинэ_систем
FROM old_users
FULL OUTER JOIN new_users ON old_users.имэйл = new_users.имэйл
WHERE old_users.имэйл IS NULL -- зөвхөн шинэ системд байгаа
OR new_users.имэйл IS NULL; -- зөвхөн хуучин системд байгаа
Хоёр хүснэгтэд аль нэгэнд нь байхгүй бичлэгийг нэгэн зэрэг олох:
-- Хичээл дуусгаагүй хэрэглэгч БА хэрэглэгчгүй хичээлүүдийг нэгэн зэрэг
SELECT
u.нэр AS хэрэглэгч,
l.гарчиг AS хичээл
FROM users AS u
FULL OUTER JOIN lesson_progress AS lp ON lp.user_id = u.id
FULL OUTER JOIN lessons AS l ON l.id = lp.lesson_id
WHERE lp.id IS NULL
ORDER BY u.нэр NULLS LAST;
CROSS JOIN — бүх хослолыг үүсгэх
CROSS JOIN нь нөхцөлгүйгээр хоёр хүснэгтийн бүх мөрийн бүх боломжит хослолыг үүсгэдэг. Үүнийг Декартын үржвэр гэнэ. Гаралтын мөрийн тоо = хүснэгт1-ийн мөр × хүснэгт2-ийн мөр.
SELECT
sizes.хэмжээ,
colors.өнгө
FROM sizes
CROSS JOIN colors;
sizes (3 мөр): S, M, L colors (3 мөр): улаан, цэнхэр, ногоон
хэмжээ | өнгө
--------+--------
S | улаан
S | цэнхэр
S | ногоон
M | улаан
M | цэнхэр
M | ногоон
L | улаан
L | цэнхэр
L | ногоон
(9 rows)
CROSS JOIN-ны бодит хэрэглээ
-- Бараа тус бүр, хэмжээ тус бүрийн агуулахын бүртгэл үүсгэх
CREATE TABLE sizes (id SERIAL PRIMARY KEY, нэр TEXT);
CREATE TABLE products (id SERIAL PRIMARY KEY, нэр TEXT);
INSERT INTO sizes VALUES (1,'S'),(2,'M'),(3,'L'),(4,'XL');
INSERT INTO products VALUES (1,'Цамц'),(2,'Өмд'),(3,'Хүрэм');
-- Бүх боломжит хослол
SELECT
p.нэр AS бараа,
s.нэр AS хэмжээ,
0 AS нөөц
FROM products AS p
CROSS JOIN sizes AS s
ORDER BY p.нэр, s.id;
бараа | хэмжээ | нөөц
---------+--------+------
Хүрэм | S | 0
Хүрэм | M | 0
Хүрэм | L | 0
Хүрэм | XL | 0
Өмд | S | 0
...
Тест өгөгдөл үүсгэхэд ч CROSS JOIN маш хэрэгтэй:
-- generate_series ба CROSS JOIN-г хослуулан тест өгөгдөл үүсгэх
INSERT INTO inventory (product_id, size_id, нөөц)
SELECT p.id, s.id, FLOOR(RANDOM() * 100)::INTEGER
FROM products AS p
CROSS JOIN sizes AS s;
JOIN-уудын харьцуулалт
-- Дараах өгөгдлөөр бүх join-г харьцуулъя:
-- А хүснэгт: 1, 2, 3
-- В хүснэгт: 2, 3, 4
-- INNER JOIN → 2, 3 (хоёуланд нь байгаа)
-- LEFT JOIN → 1, 2, 3 (А-гийн бүгд + В-ийн таарах)
-- RIGHT JOIN → 2, 3, 4 (В-ийн бүгд + А-ийн таарах)
-- FULL OUTER → 1, 2, 3, 4 (хоёуланд нь байгаагийн бүгд)
-- CROSS JOIN → 3×3 = 9 мөр (бүх хослол)
SELECT a.утга, b.утга
FROM table_a AS a
FULL OUTER JOIN table_b AS b ON a.id = b.id;
Анхааруулга: том хүснэгтэд CROSS JOIN болгоомжтой
1000 мөртэй хоёр хүснэгтийг CROSS JOIN хийвэл 1,000,000 мөр гарна. Санамсаргүй CROSS JOIN хийх нь систем гацах шалтгаан болж болно — ON нөхцөлөө мартсан эсэхийг шалга.
-- Аюултай: WHERE эсвэл ON мартсан JOIN нь санамсаргүй CROSS JOIN болдог
SELECT * FROM users, orders; -- ❌ нөхцөлгүй, аюултай
SELECT * FROM users JOIN orders ON users.id = orders.user_id; -- ✅ зөв
Дараагийн хичээлд:
COUNT, SUM, AVG, MIN, MAX зэрэг нэгтгэх функцүүдийг сурч — олон бичлэгийг нэг тоон хариу болгон боловсруулж сурна.