PostgreSQL / LEFT ба RIGHT JOIN

LEFT ба RIGHT JOIN

INNER JOIN нь хоёр хүснэгтэд хоёуланд нь таарах бичлэгийг л буцаадаг байсан. Гэхдээ заримдаа нэг талд таарахгүй байсан ч бүх бичлэгийг харах хэрэгтэй болдог — жишээ нь "нийтлэл нийтлэж байгаагүй зохиогчдыг ч оруулж харах." LEFT JOIN ба RIGHT JOIN яг энэ тохиолдолд хэрэглэнэ.

LEFT JOIN — зүүн хүснэгтийн бүгдийг хадгална

LEFT JOIN нь зүүн (FROM-ийн) хүснэгтийн БҮГД бичлэгийг буцаана. Баруун хүснэгтэд таарахгүй бол тухайн баганад NULL гарна.

Өмнөх authors ба posts жишээнд буцъя:

authors — 3 зохиогч (Болд, Сарнай, Ганбаяр) posts — зөвхөн Болд ба Сарнай нийтлэлтэй, Ганбаяр нийтлэлгүй

sql
SELECT
    a.нэр     AS зохиогч,
    p.гарчиг  AS нийтлэл
FROM authors AS a
LEFT JOIN posts AS p ON p.author_id = a.id;
код
  зохиогч  |       нийтлэл
-----------+--------------------
 Болд       | SQL суурь
 Болд       | JOIN тайлбар
 Сарнай     | Index гэж юу вэ
 Ганбаяр    | NULL

Ганбаяр нийтлэлгүй ч жагсаалтад гарч ирлээ — нийтлэл нь NULL болсон.

NULL-г ашиглан "таарахгүй" бичлэг олох

LEFT JOIN-ны хамгийн хүчирхэг хэрэглээ бол нэг хүснэгтэд байгаагүй бичлэгүүдийг олох явдал юм:

sql
-- Нийтлэл огт нийтлээгүй зохиогчдыг ол
SELECT a.нэр, a.имэйл
FROM authors AS a
LEFT JOIN posts AS p ON p.author_id = a.id
WHERE p.id IS NULL;
код
  нэр      |       имэйл
-----------+---------------------
 Ганбаяр   | ganbayar@example.com

WHERE p.id IS NULL гэдэг нь "баруун хүснэгтэд таарахгүй байсан" гэсэн утга — энэ загварыг anti-join гэж нэрлэдэг. Маш их хэрэглэгддэг!

LEFT JOIN-ны нийтлэг хэрэглээ

sql
-- Бүх хэрэглэгч ба тэдний хамгийн сүүлийн захиалга (захиалгагүй бол NULL)
SELECT
    u.нэр,
    u.имэйл,
    MAX(o.үүсгэсэн) AS сүүлийн_захиалга
FROM users AS u
LEFT JOIN orders AS o ON o.user_id = u.id
GROUP BY u.id, u.нэр, u.имэйл
ORDER BY сүүлийн_захиалга DESC NULLS LAST;
sql
-- Бүх курс ба тухайн хэрэглэгчийн гүйцэтгэлийн хувь (бүртгэлгүй бол NULL)
SELECT
    c.гарчиг AS курс,
    lp.дууссан_хичээл,
    c.нийт_хичээл
FROM courses AS c
LEFT JOIN (
    SELECT course_id, COUNT(*) AS дууссан_хичээл
    FROM lesson_progress
    WHERE user_id = 1
    GROUP BY course_id
) AS lp ON lp.course_id = c.id
ORDER BY c.id;

RIGHT JOIN — баруун хүснэгтийн бүгдийг хадгална

RIGHT JOIN нь LEFT JOIN-ны эсрэг — баруун (JOIN-ны) хүснэгтийн БҮГД бичлэгийг буцаана. Зүүн хүснэгтэд таарахгүй бол NULL гарна:

sql
SELECT
    a.нэр     AS зохиогч,
    p.гарчиг  AS нийтлэл
FROM posts AS p
RIGHT JOIN authors AS a ON p.author_id = a.id;

Энэ нь өмнөх LEFT JOIN-тэй яг адил үр дүн өгнө — хүснэгтүүдийн байрлалыг эсрэгээр бичсэн учраас.

Практик дээр RIGHT JOINLEFT JOIN-аар бичин ойлгомжтой болгох нь нийтлэг дадал:

sql
-- RIGHT JOIN ашиглан
SELECT a.нэр, p.гарчиг
FROM posts AS p
RIGHT JOIN authors AS a ON p.author_id = a.id;

-- Яг адил, гэхдээ LEFT JOIN илүү ойлгомжтой
SELECT a.нэр, p.гарчиг
FROM authors AS a
LEFT JOIN posts AS p ON p.author_id = a.id;

Ихэнх хөгжүүлэгчид RIGHT JOIN-г ховор ашигладаг — LEFT JOIN-аар дахин бичиж болдог учраас.

Олон LEFT JOIN хослуулах

sql
-- Курс бүрийн мэдээллийг, хэрэглэгч бүртгэлтэй эсэх ба дууссан хичээлийн тоотой
SELECT
    c.гарчиг                        AS курс,
    c.нийт_хичээл,
    e.бүртгэсэн_огноо,
    COUNT(lp.id)                    AS дууссан
FROM courses AS c
LEFT JOIN enrollments AS e  ON e.course_id = c.id AND e.user_id = 5
LEFT JOIN lesson_progress AS lp ON lp.course_id = c.id AND lp.user_id = 5
GROUP BY c.id, c.гарчиг, c.нийт_хичээл, e.бүртгэсэн_огноо
ORDER BY c.id;

LEFT JOIN vs INNER JOIN — хэзээ алийг сонгох вэ?

| Асуулт | JOIN сонголт | |--------|-------------| | Хоёр хүснэгтэд хоёуланд нь байгаа бичлэгийг л хар | INNER JOIN | | Нэг талын бүгдийг, нөгөө талынхыг байвал нь хамт хар | LEFT JOIN | | Таарахгүй байгаа бичлэгийг ол | LEFT JOIN ... WHERE нөгөө.id IS NULL |

Дүрэм болгон: "бүх ... + байвал нь ..." гэж бодвол LEFT JOIN. Жишээ нь "бүх хэрэглэгч + тэдний захиалга байвал нь" → LEFT JOIN.

Дараагийн хичээлд:

FULL OUTER JOIN ба CROSS JOIN-г сурна — хоёр хүснэгтийн бүгдийг нэгэн зэрэг харах ба Декартын үржвэр гэх дэвшилтэт загваруудыг ойлгоно.