7-bo‘lim

JOIN va LATERAL

JOIN turlari, LEFT JOIN bilan yo'qolgan qatorlarni topish, LATERAL nima va har guruhdan eng yaxshi N tani qanday olish.

🕑 9 daqiqa o‘qish 📄 541 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. JOIN turlari
  2. Yo'qolgan qatorlarni topish
  3. LATERAL - har guruhdan eng yaxshi N ta
  4. Jadvalni o'zi bilan birlashtirish
  5. Xulosa

JOIN ni siz bilasiz. Bu bo'limda uning nozik joylarini va PostgreSQL ning LATERAL imkoniyatini ko'ramiz.

SQL
CREATE TABLE muallif (
    id  int GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    ism text NOT NULL
);

CREATE TABLE kitob (
    id         int GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    sarlavha   text NOT NULL,
    muallif_id int REFERENCES muallif(id),
    narx       numeric(10,2) NOT NULL,
    sotilgan   int NOT NULL DEFAULT 0
);

INSERT INTO muallif (ism) VALUES
    ('Abdulla Qodiriy'), ('Cho''lpon'), ('Oybek'), ('Hali kitobsiz');

INSERT INTO kitob (sarlavha, muallif_id, narx, sotilgan) VALUES
    ('O''tkan kunlar',    1, 45000, 320),
    ('Mehrobdan chayon',  1, 38000, 210),
    ('Obid ketmon',       1, 29000,  95),
    ('Kecha va kunduz',   2, 42000, 180),
    ('Bahor qaytmaydi',   2, 35000, 140),
    ('Navoiy',            3, 52000, 260),
    ('Qutlug'' qon',      3, 48000, 175),
    ('Nomsiz kitob',   NULL, 15000,   5);

JOIN turlari #

Qaysi qatorlar natijaga tushadi INNER JOIN faqat moslar LEFT JOIN chapdagi hammasi RIGHT JOIN o'ngdagi hammasi FULL JOIN ikkala tomon Amaliy qoida "Hamma mualliflar, kitobi bo'lmasa ham" - bu LEFT JOIN "Faqat kitobi bor mualliflar" - bu INNER JOIN Savolni gapda ayting - JOIN turi o'z-o'zidan chiqadi
RIGHT JOIN kamdan-kam ishlatiladi - odatda jadvallarni almashtirib LEFT yozish tushunarliroq

INNER JOIN faqat mos kelgan qatorlarni beradi:

SQL
SELECT m.ism, k.sarlavha
FROM muallif m
JOIN kitob k ON k.muallif_id = m.id
ORDER BY m.ism, k.sarlavha
LIMIT 4;
Natija
       ism       |     sarlavha
-----------------+------------------
 Abdulla Qodiriy | Mehrobdan chayon
 Abdulla Qodiriy | O'tkan kunlar
 Abdulla Qodiriy | Obid ketmon
 Cho'lpon        | Bahor qaytmaydi
(4 rows)

LEFT JOIN esa chap jadvalning hamma qatorini saqlaydi:

SQL
SELECT m.ism, count(k.id) AS kitoblar
FROM muallif m
LEFT JOIN kitob k ON k.muallif_id = m.id
GROUP BY m.ism
ORDER BY kitoblar DESC, m.ism;
Natija
       ism       | kitoblar
-----------------+----------
 Abdulla Qodiriy |        3
 Cho'lpon        |        2
 Oybek           |        2
 Hali kitobsiz   |        0
(4 rows)

"Hali kitobsiz" muallifi ham chiqdi - 0 bilan. INNER JOIN da u umuman ko'rinmasdi.

count(*) va count(ustun) farqi

Yuqorida count(k.id) yozilgan, count(*) emas. Bu juda muhim.

YozuvLEFT JOIN da nima sanaydi
count(*)Qatorlarni - mos kelmagan qator ham 1 deb sanaladi
count(k.id)Faqat NULL bo'lmagan qiymatlarni - to'g'ri javob

count(*) yozsangiz, kitobi yo'q muallif uchun 1 chiqadi - chunki LEFT JOIN baribir bitta qator qaytaradi, faqat ustunlari NULL bo'ladi.

Bu hisobotlardagi eng nozik xatolardan biri: son bir qarashda to'g'ri ko'rinadi, lekin hamma nol o'rniga bir bo'lib chiqadi.

Yo'qolgan qatorlarni topish #

LEFT JOIN ning klassik ishlatilishi - "bog'lanmagan" qatorlarni topish:

SQL
SELECT k.sarlavha
FROM kitob k
LEFT JOIN muallif m ON m.id = k.muallif_id
WHERE m.id IS NULL;
Natija
   sarlavha
--------------
 Nomsiz kitob
(1 row)

WHERE m.id IS NULL - bu "moslik topilmadi" degani. Shu yo'l bilan yetim qolgan yozuvlarni topish mumkin.

LATERAL - har guruhdan eng yaxshi N ta #

Endi qiyinroq vazifa: har bir muallifning eng ko'p sotilgan ikkita kitobi.

Oddiy JOIN bilan buni yozib bo'lmaydi - chunki ichki so'rovga tashqi qatorning qiymati kerak. LATERAL aynan shunga ruxsat beradi:

SQL
SELECT m.ism, top.sarlavha, top.sotilgan
FROM muallif m
JOIN LATERAL (
    SELECT k.sarlavha, k.sotilgan
    FROM kitob k
    WHERE k.muallif_id = m.id
    ORDER BY k.sotilgan DESC
    LIMIT 2
) top ON true
ORDER BY m.ism, top.sotilgan DESC;
Natija
       ism       |     sarlavha     | sotilgan
-----------------+------------------+----------
 Abdulla Qodiriy | O'tkan kunlar    |      320
 Abdulla Qodiriy | Mehrobdan chayon |      210
 Cho'lpon        | Kecha va kunduz  |      180
 Cho'lpon        | Bahor qaytmaydi  |      140
 Oybek           | Navoiy           |      260
 Oybek           | Qutlug' qon      |      175
(6 rows)
LATERAL ni qanday tushunish kerak

Oddiy ichki so'rov mustaqil hisoblanadi: u tashqi so'rov haqida hech narsa bilmaydi.

LATERAL esa ichki so'rovga tashqi qatorga murojaat qilishga ruxsat beradi. Yuqoridagi misolda m.id aynan shu sababli ishladi.

Ishlash tartibini shunday tasavvur qiling: baza tashqi jadvalning har qatori uchun ichki so'rovni qaytadan bajaradi - xuddi halqa kabi.

ON true yozuvi g'alati ko'rinadi, lekin u shunchaki "hamma narsani birlashtir" degani - chunki filtrlash allaqachon ichkarida bajarilgan.

LATERAL ni LEFT JOIN bilan ishlatish ham mumkin - u holda kitobi yo'q muallif ham qoladi:

SQL
SELECT m.ism, top.sarlavha
FROM muallif m
LEFT JOIN LATERAL (
    SELECT k.sarlavha FROM kitob k
    WHERE k.muallif_id = m.id
    ORDER BY k.sotilgan DESC LIMIT 1
) top ON true
ORDER BY m.ism;
Natija
       ism       |    sarlavha
-----------------+-----------------
 Abdulla Qodiriy | O'tkan kunlar
 Cho'lpon        | Kecha va kunduz
 Hali kitobsiz   |
 Oybek           | Navoiy
(4 rows)

Jadvalni o'zi bilan birlashtirish #

Bir xil jadvalning ikki qatorini solishtirish kerak bo'lsa, uni ikki marta ishlatish mumkin:

SQL
SELECT a.sarlavha AS birinchi, b.sarlavha AS ikkinchi, a.narx
FROM kitob a
JOIN kitob b ON a.narx = b.narx AND a.id < b.id;
Natija
 birinchi | ikkinchi | narx
----------+----------+------
(0 rows)

a.id < b.id sharti ikkita narsani qiladi: qatorni o'zi bilan solishtirishni to'xtatadi va har juftlikni bir marta ko'rsatadi.

Amaliy topshiriq
  1. INNER JOIN bilan muallif va kitob nomlarini chiqaring.
  2. Uni LEFT JOIN ga o'zgartiring - nechta qator qo'shildi?
  3. count(*) va count(k.id) natijalarini solishtiring.
  4. Farq nima uchun paydo bo'lganini yozing.
  5. Muallifi yo'q kitoblarni toping.
  6. LATERAL bilan har muallifning eng qimmat kitobini chiqaring.
  7. LIMIT 2 ni LIMIT 3 ga o'zgartiring.
  8. JOIN LATERAL ni LEFT JOIN LATERAL ga almashtiring - farq nima?
  9. ON true nima uchun yozilishini tushuntiring.
  10. Narxi bir xil kitob juftliklarini toping.

Xulosa #

  • INNER JOIN faqat mos kelgan qatorlarni, LEFT JOIN esa chapdagi hammasini qaytaradi.
  • Savolni o'zbekcha gapda ayting - kerakli JOIN turi o'z-o'zidan aniqlanadi.
  • LEFT JOIN da count(*) ishlatmang - u mos kelmagan qatorni ham 1 deb sanaydi.
  • To'g'ri yozuv: count(bog'langan_ustun).
  • WHERE ... IS NULL bilan bog'lanmagan (yetim) qatorlarni topish mumkin.
  • LATERAL ichki so'rovga tashqi qatorga murojaat qilish imkonini beradi.
  • U "har guruhdan eng yaxshi N ta" vazifasini tabiiy hal qiladi.
  • LEFT JOIN LATERAL ... ON true bo'sh guruhlarni ham saqlaydi.
  • Jadvalni o'zi bilan birlashtirganda a.id < b.id shartini qo'ying.
  • RIGHT JOIN kamdan-kam kerak - jadvallarni almashtirib LEFT yozish tushunarliroq.

Keyingi bo'limda agregat funksiyalarning PostgreSQL ga xos kengaytmalarini ko'ramiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.