Oldingi darsda INNER JOIN bilan ikki jadvalni bog'lashni o'rgandik. U faqat mos juftlik topilgan qatorlarni qaytaradi. Ya'ni mijoz bilan uning buyurtmasini birlashtirganda, faqat kamida bitta buyurtmasi bor mijozlar natijada qoladi.
Lekin biz mijozlar jadvalida hech qanday buyurtma qilmagan mijozlar borligini bilamiz. Quyidagi jadvallarga e'tibor bering:
mijozlar:
| id | ism | shahar | yosh |
|---|---|---|---|
| 1 | Ali | Toshkent | 25 |
| 2 | Vali | Samarqand | 30 |
| 3 | Soli | Toshkent | 22 |
| 4 | Guli | Buxoro | 35 |
| 5 | Dilnoza | Toshkent | 28 |
| 6 | Jasur | Samarqand | 40 |
buyurtmalar (mijoz_id → mijozlar.id):
| id | mijoz_id | mahsulot_id | soni | sana |
|---|---|---|---|---|
| 1 | 1 | 1 | 1 | 2024-01-15 |
| 2 | 1 | 4 | 3 | 2024-01-20 |
| 3 | 2 | 2 | 1 | 2024-02-05 |
| 4 | 3 | 6 | 10 | 2024-02-10 |
| 5 | 5 | 3 | 2 | 2024-03-01 |
| 6 | 1 | 5 | 5 | 2024-03-15 |
| 7 | 6 | 8 | 4 | 2024-03-20 |
E'tibor bering: buyurtmalar jadvalida mijoz_id ustunida hech qaerda 4 raqami yo'q. Demak Guli (id = 4) hech qachon buyurtma qilmagan. Agar biz INNER JOIN ishlatsak, Guli natijada umuman ko'rinmaydi — chunki unga mos buyurtma yo'q.
Ko'pincha esa bizga aynan shunday mijozlar ham kerak bo'ladi: "qaysi mijoz hali hech narsa sotib olmagan?" degan savolga javob berish uchun ularni ko'rishimiz shart.
Mana shu yerda LEFT JOIN yordam beradi. U chap jadvaldagi (so'rovda FROM dan keyin birinchi yozilgan jadval) barcha qatorlarni saqlaydi. O'ng jadvalda mos juftlik topilsa — uni qo'shadi; topilmasa — o'ng tomon ustunlari NULL (bo'sh) bo'lib qoladi.
Har bir mijozni uning buyurtmalari bilan bog'laymiz:
SELECT mijozlar.ism, buyurtmalar.id
FROM mijozlar
LEFT JOIN buyurtmalar ON mijozlar.id = buyurtmalar.mijoz_id;Natija (tartibsiz):
Ali|1
Ali|2
Ali|6
Vali|3
Soli|4
Guli|
Dilnoza|5
Jasur|7Diqqat qiling: Guli ham natijada bor — lekin uning buyurtma id'si bo'sh (NULL). Chunki buyurtmalar jadvalida unga mos qator yo'q, LEFT JOIN esa baribir uni chap jadvaldan oladi va o'ng ustunlarni bo'sh qoldiradi.
Muhim: Bo'sh (NULL) qiymat natijada
|belgisidan keyin hech narsa bo'lmasligi bilan ko'rinadi — masalanGuli|qatorida ikkinchi ustun butunlay bo'sh.
FROM va LEFT JOIN jadvallarining tartibi muhim. "Chap" — bu FROM dan keyingi jadval. Biz mijozlar ni chapga qo'yganimiz uchun, hatto buyurtmasiz mijoz ham yo'qolmaydi.
So'rovni qisqaroq yozish uchun jadvallarga qisqa nom (alias) berish mumkin. Jadval nomidan keyin bir harf yozsak kifoya:
SELECT m.ism, b.id
FROM mijozlar m
LEFT JOIN buyurtmalar b ON m.id = b.mijoz_id;Bu yuqoridagi so'rov bilan aynan bir xil ishlaydi: m — mijozlar, b — buyurtmalar degani. Endi har safar to'liq jadval nomini yozish shart emas.
Endi har bir mijoz nechta buyurtma qilganini sanaymiz. Buning uchun LEFT JOIN ni GROUP BY va COUNT bilan birlashtiramiz. Lekin bu yerda bitta nozik nuqta bor.
COUNT(*) barcha qatorlarni (NULL larni ham) sanaydi. Buyurtmasiz mijoz uchun esa bitta "bo'sh" qator bor — COUNT(*) uni xato qilib 1 deb sanab qo'yadi.
Shuning uchun ustun nomini sanaymiz: COUNT(b.id). Bu funksiya b.id NULL bo'lgan qatorlarni e'tiborga olmaydi. Demak buyurtmasiz mijoz uchun u to'g'ri 0 beradi:
SELECT m.ism, COUNT(b.id)
FROM mijozlar m
LEFT JOIN buyurtmalar b ON m.id = b.mijoz_id
GROUP BY m.id
ORDER BY m.ism;Natija:
Ali|3
Dilnoza|1
Guli|0
Jasur|1
Soli|1
Vali|1Mana — Guli uchun 0 chiqdi, lekin u baribir ro'yxatda qoldi. Aynan shunga LEFT JOIN kerak edi.
Eslatma:
LEFT JOINbilan sanaganda doimoCOUNT(b.id)(o'ng jadval ustuni) yozing,COUNT(*)emas. Aks holda buyurtmasiz mijozlar ham1bo'lib chiqib, hisob noto'g'ri bo'ladi.
GROUP BY m.id ni ishlatdik (m.ism emas), chunki id har bir mijoz uchun noyob — bir xil ismli ikki mijoz bo'lsa ham ular alohida sanaladi. Natija bir nechta qator qaytargani uchun oxiriga ORDER BY m.ism qo'shib, alifbo tartibini ta'minladik.
Pastdagi kod oynasida mijozlar va buyurtmalar jadvallari allaqachon yaratilgan va to'ldirilgan. Sizning vazifangiz — har bir mijoz uchun uning buyurtmalari sonini chiqaruvchi so'rov yozish. Hech qachon buyurtma qilmagan mijoz ham natijada 0 qiymati bilan ko'rinishi kerak (LEFT JOIN + COUNT(b.id)). Natijani ism bo'yicha alifbo tartibida tartiblang.