O'tgan darsda biz skalyar quyi so'rov bilan tanishdik — u faqat bitta qiymat qaytaradi (masalan, o'rtacha narx) va uni >, <, = kabi taqqoslashlar bilan ishlatamiz.
Lekin ko'pincha quyi so'rov bir nechta qiymatlardan iborat ro'yxat qaytaradi. Masalan, "buyurtma qilingan barcha mahsulotlarning id raqamlari" — bu bitta son emas, balki ro'yxat. Bunday ro'yxat bilan ishlash uchun bizga IN va NOT IN operatorlari kerak bo'ladi.
Misollar uchun mahsulotlar va buyurtmalar jadvallaridan foydalanamiz.
mahsulotlar:
| id | nomi | kategoriya | narx | ombor |
|---|---|---|---|---|
| 1 | Telefon | Elektronika | 5000000 | 10 |
| 2 | Noutbuk | Elektronika | 12000000 | 5 |
| 3 | Quloqchin | Elektronika | 300000 | 50 |
| 4 | Kitob | Kitoblar | 50000 | 100 |
| 5 | Daftar | Kanstovar | 8000 | 200 |
| 6 | Ruchka | Kanstovar | 3000 | 500 |
| 7 | Stol | Mebel | 800000 | 15 |
| 8 | Stul | Mebel | 250000 | 40 |
buyurtmalar (har bir qator — kimdir biror mahsulotni sotib olgani):
| 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 |
Eslang: IN operatorini biz allaqachon ishlatgandik. Masalan, id si 1, 2 yoki 3 bo'lgan mahsulotlarni qo'lda yozib olishimiz mumkin edi:
SELECT nomi FROM mahsulotlar WHERE id IN (1, 2, 3);Bu yerda (1, 2, 3) — biz qo'lda yozgan ro'yxat. Endi savol shunday: bu ro'yxatni qo'lda yozish o'rniga, uni boshqa so'rov hisoblab bersa-chi?
Avval buyurtmalar jadvalidagi barcha mahsulot_id qiymatlarini ko'raylik:
SELECT mahsulot_id FROM buyurtmalar;Natija:
1
4
2
6
3
5
8Bu — sotib olingan mahsulotlarning id ro'yxati. E'tibor bering: bu yerda 7-id (Stol) yo'q — demak, hech kim Stol sotib olmagan.
Endi yuqoridagi SELECT mahsulot_id FROM buyurtmalar so'rovini qavs ichiga olib, IN dan keyin ro'yxat o'rniga qo'yamiz:
SELECT nomi
FROM mahsulotlar
WHERE id IN (SELECT mahsulot_id FROM buyurtmalar)
ORDER BY nomi;So'rov ikki bosqichda ishlaydi:
1, 4, 2, 6, 3, 5, 8.id si shu ro'yxat ichida bormi? Bor bo'lsa — qatorni oladi.Ya'ni ma'lumotlar bazasi so'rovni xuddi shunday "o'qiydi":
SELECT nomi FROM mahsulotlar WHERE id IN (1, 4, 2, 6, 3, 5, 8) ORDER BY nomi;Natija — kamida bir marta buyurtma qilingan mahsulotlar:
Daftar
Kitob
Noutbuk
Quloqchin
Ruchka
Stul
TelefonEslatma: Skalyar quyi so'rov bitta qiymat qaytarib,
>yoki=bilan ishlatilardi.INbilan ishlaydigan quyi so'rov esa bitta ustun bo'yicha ko'p qator (ro'yxat) qaytaradi. Shuning uchun ichki so'rovda doim faqat bitta ustun tanlang.
Endi savolni teskari qo'yamiz: hech qachon buyurtma qilinmagan mahsulotlar qaysilar? Ya'ni id si buyurtma ro'yxatida bo'lmagan mahsulotlar.
Buning uchun IN o'rniga NOT IN ishlatamiz — u "ro'yxatda yo'q" degan ma'noni beradi:
SELECT nomi
FROM mahsulotlar
WHERE id NOT IN (SELECT mahsulot_id FROM buyurtmalar)
ORDER BY nomi;Ichki so'rov yana o'sha ro'yxatni beradi: 1, 4, 2, 6, 3, 5, 8. Tashqi so'rov esa endi bu ro'yxatda yo'q id larni qidiradi. Yuqorida ko'rganimizdek, ro'yxatda 7-id (Stol) yo'q edi:
StolMana shunday NOT IN yordamida "ro'yxatda uchramaydiganlarni topish" juda oson bo'ladi.
Muhim: Bunday savollarda — "buyurtma qilingan" yoki "buyurtma qilinmagan" — natija deyarli har doim bir nechta qator bo'ladi. Tartib kafolatlanmagani uchun natijani aniq ko'rsatmoqchi bo'lsangiz, doim
ORDER BYqo'shing (biz bu yerdaORDER BY nomibilan alifbo tartibini belgiladik).
IN (1, 4, 2, 6, 3, 5, 8) ro'yxatini biz qo'lda yozmadik — uni quyi so'rov o'zi hisoblab berdi. Ertaga yangi buyurtma kelsa, ro'yxat avtomatik yangilanadi, so'rovimiz esa o'zgarishsiz to'g'ri ishlayveradi. "Sotilgan / sotilmagan" kabi savollarga javob berishning eng tabiiy yo'li — aynan shu.
Pastdagi kod oynasida mahsulotlar, mijozlar va buyurtmalar jadvallari allaqachon yaratilgan va to'ldirilgan. Sizning vazifangiz — hech qachon buyurtma qilinmagan mahsulotlarning nomini chiqarish, ya'ni buyurtmalar jadvalida mahsulot_id si umuman uchramaydigan mahsulotlar. Buning uchun NOT IN va quyi so'rovdan foydalaning, natijani esa alifbo tartibida tartiblang.