6-bo‘lim

SELECT ning kuchli tomonlari

DISTINCT ON, NULL bilan to'g'ri ishlash, COALESCE va NULLIF, ORDER BY da NULLS FIRST, sahifalashda OFFSET muammosi.

🕑 11 daqiqa o‘qish 📄 712 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. DISTINCT ON - guruhning birinchi qatori
  2. NULL bilan ishlash
  3. COALESCE va NULLIF
  4. ORDER BY va NULL
  5. Sahifalash
  6. Xulosa

Bu bo'limda SELECT ning PostgreSQL ga xos imkoniyatlarini ko'ramiz. Ular ko'p yozuvni qisqartiradi va ba'zi klassik xatolarning oldini oladi.

SQL
CREATE TABLE ijara (
    id        int GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    oquvchi   text NOT NULL,
    kitob     text NOT NULL,
    olingan   date NOT NULL,
    qaytargan date
);

INSERT INTO ijara (oquvchi, kitob, olingan, qaytargan) VALUES
    ('Husanboy', 'O''tkan kunlar',     '2026-01-10', '2026-01-24'),
    ('Husanboy', 'Kecha va kunduz',    '2026-02-05', NULL),
    ('Husanboy', 'Mehrobdan chayon',   '2026-03-01', '2026-03-12'),
    ('Malika',   'O''tkan kunlar',     '2026-01-15', '2026-01-20'),
    ('Malika',   'Urush va tinchlik',  '2026-02-20', NULL),
    ('Nodira',   'Kecha va kunduz',    '2026-03-05', '2026-03-18');

DISTINCT ON - guruhning birinchi qatori #

Klassik vazifa: "har bir o'quvchining eng oxirgi ijarasini ko'rsat".

Ko'p bazalarda buni yozish uchun ichki so'rov yoki oyna funksiyasi kerak. PostgreSQL da esa:

SQL
SELECT DISTINCT ON (oquvchi) oquvchi, kitob, olingan
FROM ijara
ORDER BY oquvchi, olingan DESC;
Natija
 oquvchi  |       kitob       |  olingan
----------+-------------------+------------
 Husanboy | Mehrobdan chayon  | 2026-03-01
 Malika   | Urush va tinchlik | 2026-02-20
 Nodira   | Kecha va kunduz   | 2026-03-05
(3 rows)

Qoida ikkita va ular birga ishlaydi:

QismVazifasi
DISTINCT ON (oquvchi)Har oquvchi uchun bitta qator qoldiradi
ORDER BY oquvchi, olingan DESCQaysi qator qolishini belgilaydi
ORDER BY ning boshi DISTINCT ON bilan bir xil bo'lishi shart

Bu eng ko'p uchraydigan xato. ORDER BY da birinchi ustun DISTINCT ON dagi ustun bo'lmasa, PostgreSQL xato beradi.

Mantiq oddiy: baza avval qatorlarni tartiblaydi, keyin har guruhdan birinchisini oladi. Tartiblash guruh bo'yicha boshlanmasa, "birinchi" tushunchasi ma'nosini yo'qotadi.

Ikkinchi ustun esa siz tanlaysiz: olingan DESC - eng yangisi, olingan ASC - eng eskisi.

NULL bilan ishlash #

NULL - bu "noma'lum". Uning bilan taqqoslash har doim NULL beradi, hatto o'zi bilan ham:

SQL
SELECT NULL = NULL            AS oddiy_tenglik,
       NULL IS NULL           AS is_null,
       NULL IS NOT DISTINCT FROM NULL AS aqlli_tenglik,
       1 IS DISTINCT FROM NULL AS farq_qiladimi;
Natija
 oddiy_tenglik | is_null | aqlli_tenglik | farq_qiladimi
---------------+---------+---------------+---------------
               | t       | t             | t
(1 row)

IS NOT DISTINCT FROM - bu "NULL ni ham hisobga oladigan tenglik". Ikkala tomon NULL bo'lsa, u rost beradi.

Amalda bu qaytarilmagan kitoblarni topishda kerak bo'ladi:

SQL
SELECT oquvchi, kitob
FROM ijara
WHERE qaytargan IS NULL
ORDER BY oquvchi;
Natija
 oquvchi  |       kitob
----------+-------------------
 Husanboy | Kecha va kunduz
 Malika   | Urush va tinchlik
(2 rows)
= NULL hech qachon ishlamaydi

Bu xatoni hamma qiladi:

SQL
WHERE qaytargan = NULL

Bu so'rov hech qachon qator qaytarmaydi. Xato ham bermaydi - shunchaki bo'sh natija.

Sabab: qaytargan = NULL ifodasi NULL ga teng, NULL esa WHERE uchun "rost emas" degani.

To'g'ri yozuv har doim IS NULL yoki IS NOT NULL.

Xuddi shu sabab bilan NOT IN ro'yxatida NULL bo'lsa, so'rov jimgina bo'sh natija beradi - bu ancha nozik tuzoq.

COALESCE va NULLIF #

COALESCE birinchi NULL bo'lmagan qiymatni qaytaradi:

SQL
SELECT oquvchi,
       kitob,
       COALESCE(qaytargan::text, 'hali qaytarilmagan') AS holat
FROM ijara
WHERE oquvchi = 'Husanboy'
ORDER BY olingan;
Natija
 oquvchi  |      kitob       |       holat
----------+------------------+--------------------
 Husanboy | O'tkan kunlar    | 2026-01-24
 Husanboy | Kecha va kunduz  | hali qaytarilmagan
 Husanboy | Mehrobdan chayon | 2026-03-12
(3 rows)

NULLIF esa teskarisi - ikki qiymat teng bo'lsa NULL qaytaradi. U nolga bo'lishdan himoya qilishda qulay:

SQL
SELECT 100 / NULLIF(0, 0) AS xavfsiz,
       COALESCE(100 / NULLIF(0, 0), -1) AS standart_bilan;
Natija
 xavfsiz | standart_bilan
---------+----------------
         |             -1
(1 row)

Agar NULLIF bo'lmaganda, 100 / 0 xato berib, butun so'rov to'xtardi. Endi esa NULL qaytdi va uni COALESCE bilan almashtirish mumkin.

ORDER BY va NULL #

Saralashda NULL qayerga tushadi? PostgreSQL da standart qoida bor, lekin uni o'zgartirish mumkin:

SQL
SELECT oquvchi, kitob, qaytargan
FROM ijara
ORDER BY qaytargan DESC NULLS LAST, oquvchi;
Natija
 oquvchi  |       kitob       | qaytargan
----------+-------------------+------------
 Nodira   | Kecha va kunduz   | 2026-03-18
 Husanboy | Mehrobdan chayon  | 2026-03-12
 Husanboy | O'tkan kunlar     | 2026-01-24
 Malika   | O'tkan kunlar     | 2026-01-20
 Husanboy | Kecha va kunduz   |
 Malika   | Urush va tinchlik |
(6 rows)

Oxirgi ikki qatorga qarang: qaytargan bo'sh bo'lganlar oxirida turibdi - biz shuni so'radik.

YozuvNULL qayerda
ORDER BY x ASCoxirida (standart)
ORDER BY x DESCboshida (standart)
ORDER BY x NULLS FIRSTboshida
ORDER BY x NULLS LASToxirida

Standart qoida chalkash, shuning uchun muhim hisobotlarda NULLS FIRST yoki NULLS LAST ni ochiq yozing.

Sahifalash #

LIMIT va OFFSET oddiy va tanish:

SQL
SELECT id, oquvchi, kitob
FROM ijara
ORDER BY id
LIMIT 3 OFFSET 2;
Natija
 id | oquvchi  |       kitob
----+----------+-------------------
  3 | Husanboy | Mehrobdan chayon
  4 | Malika   | O'tkan kunlar
  5 | Malika   | Urush va tinchlik
(3 rows)
Nima uchun OFFSET katta sahifalarda sekinlashadi OFFSET 100000 LIMIT 10 100 000 qator o'qiladi va TASHLAB YUBORILADI 10 ta kerak Sahifa raqami oshgan sari ish ham oshadi - 500-sahifa 1-sahifadan ancha sekin Kalit bo'yicha sahifalash indeksdan sakrash 10 ta - boshqa hech narsa o'qilmaydi WHERE id > 100500 ORDER BY id LIMIT 10 Oxirgi ko'rilgan id ni eslab qolib, keyingi so'rovda undan davom etiladi Tezlik sahifa raqamiga umuman bog'liq emas Narxi: "500-sahifaga o't" tugmasini qilib bo'lmaydi
Cheksiz aylantirish (infinite scroll) uchun ikkinchi usul ideal
Qachon OFFSET yetarli

Hamma joyda kalit bo'yicha sahifalashga o'tish shart emas.

HolatTavsiya
Admin panel, 10-20 sahifaOFFSET mos
Cheksiz aylantirishKalit bo'yicha
Millionlab qator, chuqur sahifalarKalit bo'yicha
Eksport (hammasini o'qish)Kursor yoki kalit bo'yicha

OFFSET ning yana bir kamchiligi bor: sahifalar orasida yangi qator qo'shilsa, ba'zi yozuvlar ikki marta ko'rinadi yoki tushib qoladi. Kalit bo'yicha usulda bu muammo yo'q.

Amaliy topshiriq
  1. Har o'quvchining eng eski ijarasini DISTINCT ON bilan toping.
  2. Buning uchun ORDER BY da nimani o'zgartirish kerak?
  3. ORDER BY dan oquvchi ni olib tashlang - qanday xato chiqdi?
  4. NULL = NULL va NULL IS NULL farqini yozing.
  5. WHERE qaytargan = NULL ni sinang va natijani izohlang.
  6. COALESCE bilan bo'sh qiymatga matn qo'ying.
  7. NULLIF yordamida nolga bo'lishdan himoyalaning.
  8. NULLS FIRST va NULLS LAST natijalarini solishtiring.
  9. OFFSET nima uchun katta sahifalarda sekinlashishini tushuntiring.
  10. Kalit bo'yicha sahifalashning kamchiligini yozing.

Xulosa #

  • DISTINCT ON har guruhdan bitta qator qoldiradi - qaysinisi ORDER BY bilan hal qilinadi.
  • ORDER BY ning birinchi ustuni DISTINCT ON dagi ustun bilan bir xil bo'lishi shart.
  • NULL - "noma'lum"; u hech narsa bilan, hatto o'zi bilan ham teng emas.
  • = NULL hech qachon ishlamaydi - har doim IS NULL yozing.
  • IS NOT DISTINCT FROM - NULL ni ham hisobga oladigan tenglik.
  • COALESCE birinchi NULL bo'lmagan qiymatni qaytaradi.
  • NULLIF nolga bo'lishdan himoya qilishning eng ixcham yo'li.
  • Saralashda NULL ning o'rnini NULLS FIRST / NULLS LAST bilan aniq belgilang.
  • Katta OFFSET sekin: baza tashlab yuboradigan qatorlarni ham o'qiydi.
  • Chuqur sahifalash uchun kalit bo'yicha usul ishlatiladi.

Keyingi bo'limda jadvallarni birlashtiramiz va PostgreSQL ning LATERAL imkoniyati bilan tanishamiz.

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.