IlmHamroh
JavaScript Full-stack/26-qism. SQL va PostgreSQL19/64-dars18 daqiqa
Mundarija (31)

SQL NULL mantiqi: uch qiymatli mantiq, IS NULL, COALESCE va NOT IN tuzog'i

Qisqacha: SQL'da NULL — "qiymat noma'lum" degani, nol ham, bo'sh satr ham emas. Noma'lum narsa bilan har qanday taqqoslash (NULL = NULL ham) yana noma'lum — NULL beradi, WHERE esa faqat true ni o'tkazadi. Shuning uchun = NULL emas, IS NULL; "teng emas, NULL ham hisobga" uchun — IS DISTINCT FROM. COALESCE bo'sh qiymat o'rniga zaxira beradi. Eng xavfli tuzoq: NOT IN ro'yxatida bitta NULL bo'lsa, natija doim bo'sh — o'rniga NOT EXISTS ishlating.

Bu darsda

  • NULL nima ekanini va JavaScript'dagi null dan farqini tushuntira olasiz.
  • Uch qiymatli mantiq (true, false, NULL) jadvalini bilasiz va WHERE ga ta'sirini oldindan aytasiz.
  • IS NULL, IS DISTINCT FROM, COALESCE, NULLIF ni to'g'ri ishlatasiz.
  • NOT IN + NULL tuzog'ini tanib, NOT EXISTS bilan almashtirasiz.
  • Agregatlar, CHECK, UNIQUE va ORDER BY NULL bilan qanday ishlashini bilasiz.

Oldin bilishingiz kerak: SELECT va WHERE, ORDER BY, LIMIT va OFFSET, CREATE TABLE va cheklovlar.

1. Nega bu kerak?

SELECT va WHERE darsida NOT IN haqida "ro'yxatda NULL bo'lsa — natija doim bo'sh" deb ogohlantirgan edik. ORDER BY darsida NULL saralashda "eng katta" bo'lib chiqdi. Endi buning sababini tushunamiz.

Hayotiy vaziyat. Ro'yxatdan o'tishda telefon raqami ixtiyoriy. Malika uni kiritmadi. Bazada uning telefoni nima bo'lishi kerak?

  • '' (bo'sh satr) — "telefoni bor, u bo'sh" degan g'alati gap.
  • '0' — "telefoni 0" — yolg'on.
  • NULL — "bilmaymiz". Aynan shu.

Muammo shundaki, "bilmaymiz" bilan hisoblash odatiy mantiqdan boshqacha ishlaydi. "Malikaning telefoni Azizniki bilan bir xilmi?" — Javob "ha" ham, "yo'q" ham emas, "bilmaymiz". SQL ham aynan shunday javob beradi. Va bu ko'p dasturchini chalg'itadi: so'rov xatosiz ishlaydi, lekin bir qism qatorlar jim yo'qoladi.

O'xshatish: yopiq konvert. Ikki konvertda pul bor, lekin ochilmagan. "Ikkalasida bir xil pulmi?" — bilmaysiz. "Birinchisida 100 000 so'mdan ko'pmi?" — bilmaysiz. Konvertni ochmaguningizcha har savolga javob — "noma'lum".

2. NULL — "noma'lum"

2.1 JavaScript bilan farqi

JavaScript'da null === null — true. SQL'da esa NULL = NULL — true emas. Kanon (PostgreSQL 18.6):

sql
SELECT NULL = NULL AS teng,
       NULL <> 1 AS farq,
       NULL IS NULL AS isnull,
       true AND NULL AS va,
       true OR NULL AS yoki,
       NOT NULL::boolean AS emas;

Natija:

text
 teng | farq | isnull | va | yoki | emas 
------+------+--------+----+------+------
      |      | t      |    | t    | 
(1 row)

Bo'sh kataklar — NULL. psql uni sukut bo'yicha bo'sh joy qilib ko'rsatadi, shuning uchun ko'rish qiyin. Buni tuzatamiz.

2.2 psql'da NULL'ni ko'rinadigan qilish

\pset null — psql'ga "NULL o'rniga shu belgini chiqar" deydi. Biz ishga tushirdik (PostgreSQL 17.6, Windows 11):

text
vazifalar=# \pset null '∅'
Null display is "∅".

Endi kichik jadvalni chiqaramiz:

sql
SELECT nom, x
FROM (VALUES ('a', 1), ('b', NULL), ('c', 2)) AS t (nom, x);

Natija:

text
 nom | x 
-----+---
 a   | 1
 b   | ∅
 c   | 2
(3 rows)

Endi b ning x i bo'sh satr emas, NULL ekani aniq. Bu darsning qolgan "biz ishga tushirdik" chiqishlarida ∅ — NULL. Doimiy qilish uchun \pset null '∅' ni .psqlrc ga yozing (psql chuqur). Kanon chiqishlarida esa NULL — bo'sh joy.

2.3 Noma'lum bilan har amal — noma'lum

Taqqoslashgina emas, deyarli har amal NULL bilan NULL beradi. Biz ishga tushirdik (PostgreSQL 17.6):

sql
SELECT 'Aziz' || NULL AS ulash,
       NULL + 1 AS qoshish,
       length(NULL) AS uzunlik;

Natija:

text
 ulash | qoshish | uzunlik 
-------+---------+---------
 ∅     |       ∅ |       ∅
(1 row)

"Aziz + noma'lum narsa" — noma'lum. JavaScript'dagi "Aziz" + null → "Aziznull" kabi g'alati natija yo'q, lekin NULL "yuqumli": u ifoda bo'ylab tarqaladi. (concat funksiyasi bundan istisno — Ifodalar va o'rnatilgan funksiyalar darsida.)

3. Uch qiymatli mantiq

3.1 Jadval

SQL'da mantiqiy qiymat uchta: true, false va NULL (unknown — noma'lum). AND va OR uchun qoida: "noma'lumni true deb ham, false deb ham tasavvur qiling. Ikkala holatda javob bir xil chiqsa — o'sha javob, aks holda — NULL".

A B A AND B A OR B
true NULL NULL true
false NULL false NULL
NULL NULL NULL NULL

Misol: false AND NULL. NULL true bo'lsa ham, false bo'lsa ham false AND … — false. Demak javob aniq: false. true AND NULL esa noma'lumga bog'liq — NULL. NOT NULL — NULL (noma'lumning teskarisi ham noma'lum).

3.2 WHERE faqat true'ni o'tkazadi

Bu eng muhim qoida. WHERE qatorni natijaga faqat shart aniq true bo'lsa qo'shadi. false ham, NULL ham — tashlanadi.

flowchart LR
  A["Qator"] --> B{"WHERE sharti"}
  B -->|true| C["Natijaga kiradi"]
  B -->|false| D["Tashlanadi"]
  B -->|NULL| D

Diagrammaga qarang: NULL va false bir xil yo'ldan ketadi. Kanon (PostgreSQL 18.6) — "x 1 ga teng bo'lmaganlar":

sql
SELECT nom
FROM (VALUES ('a', 1), ('b', NULL), ('c', 2)) AS t (nom, x)
WHERE x <> 1;

Natija:

text
 nom 
-----
 c
(1 row)

b qani? Uning x i noma'lum. "Noma'lum 1 ga teng emasmi?" — noma'lum. WHERE uni tashladi. Odam mantiqi bilan b "1 emas" — lekin SQL buni bilmaydi.

Yana bir g'alati misol. Biz ishga tushirdik (PostgreSQL 17.6, holat 15):

sql
SELECT count(*) FROM vazifalar
WHERE NOT (bajarildi AND NULL);

Natija:

text
 count 
-------
    20
(1 row)

40 qatordan 20 tasi. Bajarilmaganlarda: false AND NULL = false, NOT false = true — o'tdi. Bajarilganlarda: true AND NULL = NULL, NOT NULL = NULL — tashlandi. Haqiqiy so'rovda NULL doimiy emas, nullable ustundan keladi — va xuddi shunday jim "yo'qotadi".

Tekshirib ko'ring: WHERE x = 1 OR x <> 1 hamma qatorni qaytaradimi?

Javob

Yo'q — x NULL bo'lgan qatorlardan tashqari hammasini. NULL = 1 — NULL, NULL <> 1 — NULL, NULL OR NULL — NULL. "Yoki teng, yoki teng emas" odam uchun doim rost, SQL uchun esa NULL da emas.

4. NULL bilan to'g'ri ishlash

4.1 = NULL emas, IS NULL

Boshlovchining eng birinchi xatosi. Biz ishga tushirdik (PostgreSQL 17.6):

sql
SELECT nom
FROM (VALUES ('a', 1), ('b', NULL), ('c', 2)) AS t (nom, x)
WHERE x = NULL;

SELECT nom
FROM (VALUES ('a', 1), ('b', NULL), ('c', 2)) AS t (nom, x)
WHERE x IS NULL;

Natija:

text
 nom 
-----
(0 rows)

 nom 
-----
 b
(1 row)

x = NULL — har qatorda NULL, demak hech narsa topilmaydi. Xato ham bermaydi — shuning uchun xavfli. IS NULL va IS NOT NULL — maxsus operatorlar, ular doim true yoki false qaytaradi, hech qachon NULL emas.

4.2 IS DISTINCT FROM — NULL'ni ham hisobga oladigan "teng emas"

"x 1 dan farqli bo'lganlar, NULL ham kirsin" — buni x <> 1 OR x IS NULL deb yozish mumkin. Qisqasi — IS DISTINCT FROM. U NULL ni oddiy qiymat deb taqqoslaydi: ikki NULL — "bir xil", NULL va 1 — "har xil". Kanon (PostgreSQL 18.6):

sql
SELECT NULL IS DISTINCT FROM NULL AS distinct_null,
       1 IS DISTINCT FROM NULL AS distinct_1;

SELECT nom
FROM (VALUES ('a', 1), ('b', NULL), ('c', 2)) AS t (nom, x)
WHERE x IS DISTINCT FROM 1;

Natija:

text
 distinct_null | distinct_1 
---------------+------------
 f             | t
(1 row)

 nom 
-----
 b
 c
(2 rows)

Endi b ham bor. Teskarisi — IS NOT DISTINCT FROM: NULL ni ham hisobga oladigan "teng". Bu, masalan, "qiymat o'zgardimi?" degan tekshiruvda kerak: eski NULL, yangi NULL — o'zgarmadi; eski NULL, yangi 5 — o'zgardi. Oddiy <> ikkala holatda ham NULL berardi. Bu Soft delete va tarix jadvallari darsidagi trigger'larda kerak bo'ladi.

4.3 COALESCE va NULLIF

coalesce(a, b, c) — birinchi NULL bo'lmagan qiymat. JavaScript'dagi a ?? b ?? c ga o'xshaydi. nullif(a, b) — teskarisi: a = b bo'lsa NULL, aks holda a. Kanon (PostgreSQL 18.6):

sql
SELECT coalesce(NULL, NULL, 'zaxira') AS coalesce,
       nullif(0, 0) AS nullif,
       10 / nullif(0, 0) AS nolga_bolish_yoq;

Natija:

text
 coalesce | nullif | nolga_bolish_yoq 
----------+--------+------------------
 zaxira   |        |                 
(1 row)

Uchinchi ustunga qarang: 10 / 0 xato (division by zero) bergan bo'lardi (UPDATE va DELETE xavfsiz darsida ko'rdik). 10 / nullif(0, 0) = 10 / NULL = NULL — xato yo'q. Hisobotlarda "o'rtacha = jami / soni" da soni nol bo'lishi mumkin bo'lsa — shu naqsh.

COALESCE ning odatiy ishi — ko'rsatish uchun zaxira matn: coalesce(telefon, 'kiritilmagan'). Mashqlarda buni qilamiz.

Tekshirib ko'ring: coalesce(NULL, 0, 5) va nullif('a', 'b') nima qaytaradi?

Javob

0 — birinchi NULL bo'lmagani (0 ham qiymat, NULL emas). 'a' — 'a' va 'b' teng emas, shuning uchun birinchisi qaytadi.

5. NOT IN tuzog'i

5.1 Tuzoq amalda

Savol: "Hali vazifasi yo'q foydalanuvchilar". Bir usul: foydalanuvchining id si vazifalardagi egasi_id lar ro'yxatida yo'q. Kanon (PostgreSQL 18.6):

sql
SELECT id FROM foydalanuvchilar
WHERE id NOT IN (SELECT egasi_id FROM vazifalar);

Natija:

text
 id 
----
  8
(1 row)

Shahnoza (8) — to'g'ri. Qavs ichidagi SELECT — ichki so'rov: u 40 ta egasi_id ro'yxatini beradi (Subquery va LATERAL darsida to'liq). Endi ro'yxatda bitta NULL bo'lsin. Kanon (PostgreSQL 18.6):

sql
SELECT id FROM foydalanuvchilar
WHERE id NOT IN (1, 2, 3, 4, 5, 6, 7, NULL);

Natija:

text
 id 
----
(0 rows)

Shahnoza yo'qoldi. Hech kim yo'q. Nega?

5.2 Sababi: NOT IN — bu AND zanjiri

x NOT IN (a, b, c) aslida x <> a AND x <> b AND x <> c. Shahnoza uchun:

flowchart TD
  A["8 NOT IN (1, …, 7, NULL)"] --> B["8 <> 1 AND … AND 8 <> 7<br/>AND 8 <> NULL"]
  B --> C["true AND … AND true<br/>AND NULL"]
  C --> D["NULL"]
  D --> E["WHERE tashlaydi"]

Diagrammadagi uchinchi qadamga qarang: hamma solishtirish true, faqat oxirgisi NULL. true AND NULL — NULL. Natijada hech bir id uchun shart true bo'lmaydi.

Biz buni alohida ifodalarda ham tekshirdik (PostgreSQL 17.6):

sql
SELECT 3 NOT IN (1, 2)       AS bir,
       3 NOT IN (1, 2, NULL) AS ikki,
       3 IN (1, 2, NULL)     AS uch,
       1 IN (1, NULL)        AS tort;

Natija:

text
 bir | ikki | uch | tort 
-----+------+-----+------
 t   | ∅    | ∅   | t
(1 row)

IN da NULL kamroq zarar qiladi: topilsa — true (tort), topilmasa — NULL (false o'rniga, lekin WHERE uchun farqi yo'q). NOT IN da esa NULL hamma narsani yo'qotadi.

Haqiqiy hayotda ro'yxat ichki so'rovdan keladi. Bugun egasi_id NOT NULL — tuzoq yo'q. Ertaga kimdir ustundan NOT NULL ni olib tashlaydi yoki boshqa nullable ustun ishlatadi — va so'rov jim "hech kim yo'q" deya boshlaydi. Xato xabari ham, ogohlantirish ham yo'q.

5.3 Yechim: NOT EXISTS

NOT EXISTS — "shunday qator mavjud emas". U har foydalanuvchi uchun alohida tekshiradi va NULL uni chalg'itmaydi. Kanon (PostgreSQL 18.6):

sql
SELECT id FROM foydalanuvchilar f
WHERE NOT EXISTS (
  SELECT 1 FROM vazifalar v WHERE v.egasi_id = f.id
);

Natija:

text
 id 
----
  8
(1 row)

Bu shablonni Foreign key darsida yetimlarni topishda ishlatgan edik. Qoida: "ro'yxatda yo'q" savoli uchun — NOT EXISTS, NOT IN emas (agar ro'yxat ichki so'rovdan kelsa). NOT IN (1, 2, 3) kabi qo'lda yozilgan, NULL siz ro'yxat xavfsiz.

6. NULL boshqa joylarda

6.1 Agregatlar NULL'ni tashlab ketadi

Bu bo'lim keyingi darsga ko'prik. count, sum, avg kabi agregat funksiyalar ko'p qatorni bitta songa aylantiradi (Agregatlar, GROUP BY va HAVING). Ular NULL ni e'tiborga olmaydi. Kanon (PostgreSQL 18.6):

sql
SELECT count(*) AS hammasi, count(x) AS null_emas,
       avg(x) AS ortacha, sum(x) AS yigindi
FROM (VALUES (1), (NULL), (3)) AS t (x);

Natija:

text
 hammasi | null_emas |      ortacha       | yigindi 
---------+-----------+--------------------+---------
       3 |         2 | 2.0000000000000000 |       4
(1 row)

count(*) — qatorlar soni (3). count(x) — x NULL bo'lmagan qatorlar (2). avg = 4 / 2 = 2 — NULL qator bo'luvchiga ham kirmadi. Agar "ma'lumot yo'q"ni nol deb hisoblash kerak bo'lsa — avg(coalesce(x, 0)) = 4 / 3. Qaysi biri to'g'ri — biznes savoli.

Bo'sh to'plamda esa sum — NULL, count — 0. Kanon (PostgreSQL 18.6):

sql
SELECT sum(x) AS bosh_sum, count(x) AS bosh_count
FROM (VALUES (NULL::int)) AS t (x);

Natija:

text
 bosh_sum | bosh_count 
----------+------------
          |          0
(1 row)

API'da "jami summa" null bo'lib qaytsa, frontend null.toFixed() da yiqilishi mumkin. coalesce(sum(x), 0) — odatiy himoya.

6.2 CHECK NULL'ni o'tkazadi

CHECK cheklovi qatorni faqat shart false bo'lsa rad etadi. NULL — rad etilmaydi. Biz ishga tushirdik (PostgreSQL 17.6):

sql
CREATE TEMP TABLE t19_c (narx int CHECK (narx > 0));
INSERT INTO t19_c VALUES (NULL);
INSERT INTO t19_c VALUES (-5);

Natija:

text
CREATE TABLE
INSERT 0 1
ERROR:  new row for relation "t19_c" violates check constraint "t19_c_narx_check"
DETAIL:  Failing row contains (-5).

NULL > 0 — NULL, va CHECK uni o'tkazdi. -5 > 0 — false — rad etildi. Bu ataylab shunday: "narx noma'lum" mumkin, "narx manfiy" — yo'q. Narx majburiy bo'lsa — NOT NULL ni alohida yozasiz. WHERE va CHECK qarama-qarshi ishlaydi: WHERE NULL ni tashlaydi, CHECK — o'tkazadi.

6.3 UNIQUE va NULL

UNIQUE uchun ikki NULL "teng" emas (noma'lum va noma'lum — bir xilmi? bilmaymiz). Shuning uchun bir nechta NULL yozish mumkin. PostgreSQL 15 dan NULLS NOT DISTINCT bilan buni o'zgartirsa bo'ladi. Kanon (PostgreSQL 18.6):

sql
CREATE TEMP TABLE t19_a (kod text UNIQUE);
INSERT INTO t19_a VALUES (NULL), (NULL);
SELECT count(*) AS ikki_null_otdi FROM t19_a;

CREATE TEMP TABLE t19_b (kod text UNIQUE NULLS NOT DISTINCT);
INSERT INTO t19_b VALUES (NULL), (NULL);

Natija:

text
CREATE TABLE
INSERT 0 2
 ikki_null_otdi 
----------------
              2
(1 row)

CREATE TABLE
ERROR:  duplicate key value violates unique constraint "t19_b_kod_key"
DETAIL:  Key (kod)=(null) already exists.

Sukut odatda to'g'ri: ixtiyoriy telefon ustuni UNIQUE bo'lsa, telefon kiritmagan ko'p odam bo'lishi kerak. NULLS NOT DISTINCT kamdan-kam kerak: masalan, "har foydalanuvchida ko'pi bilan bitta asosiy (NULL toifali) papka".

6.4 Tartiblash va tashqi kalit

Tekshirib ko'ring: CHECK (chegirma BETWEEN 0 AND 100) bor ustunga NULL yozilsa nima bo'ladi?

Javob

Yoziladi. NULL BETWEEN 0 AND 100 — NULL, CHECK esa faqat false ni rad etadi. Chegirma majburiy bo'lsa, NOT NULL qo'shing (yoki DEFAULT 0).

7. SQL qadami: NULL va bizning sxema (holat 15, commit yo'q)

Holat 15 da hamma ustun NOT NULL — bu ataylab. CREATE TABLE darsidagi qoida: ustun "noma'lum" bo'la olmasa — NOT NULL. Keyingi bosqichlarda ixtiyoriy ustunlar paydo bo'ladi:

Ustun (qaysi darsda) NULL ma'nosi
muddat (ALTER TABLE) Muddat belgilanmagan
bajarilgan_vaqt (ALTER TABLE) Hali bajarilmagan
ota_id (ALTER TABLE) Asosiy vazifa (otasi yo'q)
izohlar.muallif_id (Bog'lanishlar) Muallif o'chirilgan

Har birida NULL ning bitta aniq ma'nosi bor va u sxema izohida yoziladi. "Noma'lum ham, yo'q ham, hali kiritilmagan ham" — bitta NULL ga ko'p ma'no yuklash — keyinchalik xatolar manbai.

API tomonda: JSON'da null → bazada NULL, va aksincha. Lekin "maydon yuborilmadi" (undefined) va "maydonni tozalash" (null) — PATCH so'rovida ikki xil narsa. Buni 25-qism dagi validatsiya bilan farqlaysiz.

8. Ko'p uchraydigan xatolar

Xato yoki belgi Sabab Davosi
WHERE x = NULL — (0 rows) = NULL doim NULL IS NULL
<> bilan NULL qatorlar yo'qoldi NULL <> 1 — NULL IS DISTINCT FROM
NOT IN (SELECT …) — (0 rows) Ro'yxatda NULL bor NOT EXISTS
Matnni NULL bilan ulash — NULL NULL yuqumli coalesce yoki concat
division by zero Bo'luvchi 0 x / nullif(y, 0)
sum NULL qaytardi Bo'sh to'plam yoki hammasi NULL coalesce(sum(x), 0)
CHECK bor, lekin NULL yozildi CHECK NULL ni o'tkazadi NOT NULL qo'shing
psql'da bo'sh katak — NULL mi, '' mi? Ko'rinish bir xil \pset null '∅'

9. Mashqlar

1-mashq (oson): natijani toping

Javob — true, false yoki NULL:

  • NULL = NULL →
  • false AND NULL →
  • true OR NULL →
  • NULL IS NULL →
  • 5 NOT IN (1, NULL) →
  • NULL IS DISTINCT FROM 5 →
Yechim
  • NULL — noma'lumni noma'lum bilan solishtirib bo'lmaydi.
  • false — false AND har qanday narsa — false.
  • true — true OR har qanday narsa — true.
  • true — IS NULL hech qachon NULL qaytarmaydi.
  • NULL — 5 <> 1 AND 5 <> NULL = true AND NULL.
  • true — IS DISTINCT FROM NULL ni oddiy qiymat deb solishtiradi.

2-mashq (o'rta): telefonlar

VALUES jadvali: Aziz '+998 90 000 00 01', Malika NULL, Jasur '+998 91 000 00 02', Dilnoza NULL. Telefoni +998 90 bilan boshlanmaydiganlarni chiqaring — telefoni yo'qlar ham kirsin. Telefon o'rniga NULL bo'lsa "kiritilmagan" yozilsin. Ism bo'yicha tartiblang.

Ishora: NULL NOT LIKE … — NULL. LIKE — SELECT va WHERE.

Yechim
sql
SELECT ism,
       coalesce(telefon, 'kiritilmagan') AS telefon
FROM (VALUES ('Aziz',    '+998 90 000 00 01'),
             ('Malika',  NULL),
             ('Jasur',   '+998 91 000 00 02'),
             ('Dilnoza', NULL)) AS t (ism, telefon)
WHERE telefon IS NULL OR telefon NOT LIKE '+998 90%'
ORDER BY ism;

Natija (biz ishga tushirdik, PG 17.6):

text
   ism   |      telefon      
---------+-------------------
 Dilnoza | kiritilmagan
 Jasur   | +998 91 000 00 02
 Malika  | kiritilmagan
(3 rows)

telefon IS NULL OR bo'lmasa, Malika va Dilnoza tushib qolardi: ular uchun NOT LIKE — NULL. WHERE dagi telefon — asl ustun (NULL bilan), SELECT dagi coalesce faqat ko'rinishni o'zgartiradi. ORDER BY ism taxallussiz ustun — ism — bo'yicha.

3-mashq (qiyin): eslatma olmaganlar

Holat 15 da vaqtinchalik jadval yarating: eslatmalar (egasi_id bigint, matn text). Unga uchta qator yozing: Aziz (1) va Dilnoza (2) uchun shaxsiy eslatma, va bitta umumiy eslatma — egasi_id NULL. So'ng "shaxsiy eslatma olmagan foydalanuvchilar"ni ikki usulda toping: (a) NOT IN bilan, (b) NOT EXISTS bilan. Natijalarni solishtiring va farqni tushuntiring.

Yechim
sql
CREATE TEMP TABLE eslatmalar (egasi_id bigint, matn text);
INSERT INTO eslatmalar VALUES
  (1, 'Dars 19'), (2, 'Dars 19'),
  (NULL, 'Hammaga: tizim yangilandi');

-- (a) NOT IN — ro'yxatda NULL bor
SELECT id, ism FROM foydalanuvchilar
WHERE id NOT IN (SELECT egasi_id FROM eslatmalar)
ORDER BY id;

-- (b) NOT EXISTS — to'g'ri javob
SELECT id, ism FROM foydalanuvchilar f
WHERE NOT EXISTS (
  SELECT 1 FROM eslatmalar e WHERE e.egasi_id = f.id
)
ORDER BY id;

Natija (biz ishga tushirdik, PG 17.6):

text
CREATE TABLE
INSERT 0 3
 id | ism 
----+-----
(0 rows)

 id |        ism         
----+--------------------
  3 | Sardor Tursunov
  4 | Madina Yusupova
  5 | Javohir Olimov
  6 | Gulnora Saidova
  7 | Bekzod Nazarov
  8 | Shahnoza Ergasheva
(6 rows)

(a) — bo'sh: ichki so'rov {1, 2, NULL} beradi va har id uchun NOT IN — NULL. (b) — 6 kishi, to'g'ri. Umumiy eslatma hech kimga "tegishli" emas, shuning uchun u hech kimni chiqarib tashlamasligi kerak edi. NOT IN ni "tuzatish" ham mumkin (… WHERE egasi_id IS NOT NULL), lekin buni har safar eslab yurish kerak — NOT EXISTS esa doim to'g'ri.

10. Real ishda

  • Jim yo'qolgan qatorlar — "hisobotda 3 ta mijoz kam chiqyapti" kabi xatolarning katta qismi NULL va <>, NOT IN yoki LEFT JOIN dan keyingi WHERE bilan bog'liq. Kod review'da nullable ustun ko'rsangiz — darhol "NULL bo'lsa nima bo'ladi?" deb so'rang.
  • ORM va driverlar — pg NULL ni JavaScript null ga aylantiradi (node-postgres asoslari). TypeScript'da nullable ustun — string | null, NOT NULL — string. Sxemadagi NOT NULL frontendgacha tip xavfsizligini beradi.
  • Statistika — avg NULL ni tashlaydi: "o'rtacha baho" bo'sh baholarni nol deb hisoblaydimi yoki yo'qmi — mahsulot qarori, uni aniq hal qiling.
  • Intervyu savollari: "NULL = NULL nima qaytaradi?", "NOT IN va NOT EXISTS farqi?", "count(*) va count(ustun) farqi?" — uchalasi juda ko'p so'raladi.

Xulosa

  • NULL — "noma'lum": nol ham, '' ham emas; deyarli har amal NULL bilan NULL beradi.
  • Uch qiymatli mantiq: true, false, NULL; WHERE faqat true ni o'tkazadi, CHECK esa faqat false ni rad etadi.
  • IS NULL / IS NOT NULL — = NULL emas; IS DISTINCT FROM — NULL ni ham hisobga oladigan solishtirish.
  • coalesce(a, b) — zaxira qiymat; nullif(a, b) — nolga bo'lishdan himoya.
  • NOT IN ro'yxatida bitta NULL — natija bo'sh; ichki so'rov bilan doim NOT EXISTS.
  • Agregatlar NULL ni tashlaydi (count(*) ≠ count(x), bo'sh sum — NULL); UNIQUE bir nechta NULL ni o'tkazadi (NULLS NOT DISTINCT — PG 15+).

Keyingi dars: Agregatlar, GROUP BY va HAVING — qatorlarni guruhlab statistika: har foydalanuvchining vazifalari soni, FILTER, HAVING, string_agg va API uchun json_agg.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
SQL NULL mantiqi: uch qiymatli mantiq, IS NULL, COALESCE va NOT IN tuzog'i — IlmHamroh