ORDER BY, LIMIT, OFFSET — saralash va sahifalash
Muammodan boshlaylik
Internet do'kon katalogida 50 000 mahsulot. Foydalanuvchiga:
- "Arzonidan qimmatiga" tartiblash kerak
- Bir sahifada faqat 20 ta ko'rsatish kerak
- "Eng ko'p sotilgan 10 ta" bloki kerak
50 000 qatorni ilovaga olib, PHP yoki JavaScript da saralab, 20 tasini kesib olish — juda sekin va xotirani to'ldiradi. Bu ishni baza o'zi bajarishi kerak.
ORDER BY — saralash
SELECT nom, narx FROM mahsulotlar ORDER BY narx; -- o'sish (ASC — standart)
SELECT nom, narx FROM mahsulotlar ORDER BY narx DESC; -- kamayish
[!WARNING]
ORDER BYsiz natija tartibi kafolatlanmagan. Ko'pinchaidbo'yicha chiqadi, lekin bu tasodif — indeks, MySQL versiyasi yoki jadvaldagi o'zgarishlarga qarab boshqacha bo'lishi mumkin. Tartib muhim bo'lsa — doimORDER BYyozing.
Bir nechta ustun bo'yicha
SELECT nom, toifa_id, narx FROM mahsulotlar
ORDER BY toifa_id ASC, narx DESC;
Avval toifa bo'yicha, bir toifa ichida — narx bo'yicha kamayish tartibida.
Hisoblangan qiymat va taxallus bo'yicha
SELECT nom, narx * soni AS qiymat
FROM mahsulotlar
ORDER BY qiymat DESC;
ORDER BY SELECT dan keyin bajariladi, shuning uchun taxalluslar bu yerda ishlaydi (WHERE dan farqli).
NULL lar qayerga tushadi?
MySQL da NULL — eng kichik qiymat: ASC da boshida, DESC da oxirida.
-- Telefoni borlar avval, NULL lar oxirida
SELECT ism, telefon FROM mijozlar ORDER BY telefon IS NULL, telefon;
telefon IS NULL — 0 (bor) yoki 1 (yo'q). 0 lar birinchi.
O'z tartibingiz
SELECT id, holat FROM buyurtmalar
ORDER BY FIELD(holat, 'yangi', 'tolangan', 'yolda', 'yetkazildi', 'bekor');
FIELD() — qiymatning ro'yxatdagi o'rnini qaytaradi.
LIMIT — natijani cheklash
-- Eng qimmat 3 ta mahsulot
SELECT nom, narx FROM mahsulotlar ORDER BY narx DESC LIMIT 3;
+----------------+----------+
| nom | narx |
+----------------+----------+
| MacBook Air M3 | 16900000 |
| iPhone 15 | 12500000 |
| Lenovo IdeaPad | 7200000 |
+----------------+----------+
LIMIT + ORDER BY — "top N" savollarining standart yechimi.
-- Eng oxirgi buyurtma
SELECT * FROM buyurtmalar ORDER BY yaratilgan DESC LIMIT 1;
OFFSET — sahifalash
SELECT nom, narx FROM mahsulotlar ORDER BY id LIMIT 20 OFFSET 0; -- 1-sahifa
SELECT nom, narx FROM mahsulotlar ORDER BY id LIMIT 20 OFFSET 20; -- 2-sahifa
SELECT nom, narx FROM mahsulotlar ORDER BY id LIMIT 20 OFFSET 40; -- 3-sahifa
Formula: OFFSET = (sahifa - 1) × sahifa_hajmi.
Qisqa yozuv (eski kodda ko'p):
SELECT ... LIMIT 40, 20; -- OFFSET 40, LIMIT 20 — tartib teskari, chalkash!
LIMIT 20 OFFSET 40 aniqroq — shuni ishlating.
Jami sahifalar soni
"1 2 3 ... 47" tugmalarini chizish uchun jami son kerak:
SELECT COUNT(*) FROM mahsulotlar WHERE soni > 0;
Ilovada: sahifalar = CEIL(jami / 20).
Saralash noyob bo'lishi kerak
-- ❌ Bir xil narxli mahsulotlar sahifalar orasida "sakrab" yurishi mumkin
SELECT nom, narx FROM mahsulotlar ORDER BY narx LIMIT 20 OFFSET 20;
-- ✅ Noyob ustun qo'shib, tartibni barqaror qiling
SELECT nom, narx FROM mahsulotlar ORDER BY narx, id LIMIT 20 OFFSET 20;
Bir xil narxli 30 ta mahsulot bo'lsa, ularning tartibi har so'rovda boshqacha bo'lishi mumkin — biri 1-sahifada ham, 2-sahifada ham chiqadi, boshqasi umuman ko'rinmaydi.
OFFSET muammosi — chuqur sahifalar
SELECT nom FROM mahsulotlar ORDER BY id LIMIT 20 OFFSET 500000;
Bu so'rov 20 ta qator qaytaradi, lekin MySQL 500 020 ta qatorni o'qib chiqadi va birinchi 500 000 tasini tashlab yuboradi. Sahifa qanchalik uzoq bo'lsa — shunchalik sekin.
Keyset (kursor) sahifalash
"500 000 tasini o'tkazib yubor" o'rniga — "oxirgi ko'rgan id dan keyingilarini ber":
-- 1-sahifa
SELECT id, nom FROM mahsulotlar ORDER BY id LIMIT 20;
-- oxirgi qatorning id si: 20
-- Keyingi sahifa
SELECT id, nom FROM mahsulotlar WHERE id > 20 ORDER BY id LIMIT 20;
-- oxirgi id: 40
SELECT id, nom FROM mahsulotlar WHERE id > 40 ORDER BY id LIMIT 20;
id da indeks bor — MySQL to'g'ridan-to'g'ri kerakli joyga "sakraydi". Millioninchi sahifa ham birinchisidek tez.
Bir nechta ustun bo'yicha saralashda:
-- Narx bo'yicha, oxirgi ko'rilgan: narx = 4800000, id = 2
SELECT id, nom, narx FROM mahsulotlar
WHERE (narx, id) > (4800000, 2)
ORDER BY narx, id
LIMIT 20;
| OFFSET | Keyset | |
|---|---|---|
| "47-sahifaga o'tish" | ✅ Mumkin | ❌ Faqat "keyingi/oldingi" |
| Chuqur sahifalar tezligi | Sekinlashadi | Doim tez |
| Yangi qator qo'shilsa | Qatorlar takrorlanishi/yo'qolishi mumkin | Barqaror |
| Qayerda | Admin panellar, kichik ro'yxatlar | Cheksiz lenta, API, mobil ilovalar |
Instagram, Twitter lentalari — keyset sahifalash.
Nima uchun shunday?
Nima uchun saralash va kesishni ilovada emas, bazada qilish kerak?
Chunki baza indekslardan foydalanadi. narx ustunida indeks bo'lsa, ma'lumot u yerda allaqachon tartiblangan holda saqlanadi — ORDER BY narx LIMIT 20 uchun MySQL indeksning boshidan 20 ta yozuvni o'qiydi va tamom. Ilova esa 50 000 qatorni tarmoq orqali olishi, xotiraga joylashi va saralashi kerak. Farq — millisekundlar va soniyalar.
Xulosa
Eslab qoling:
ORDER BY ustun [ASC|DESC]— tartib muhim bo'lsa doim yozing- Bir nechta ustun:
ORDER BY a, b DESC LIMIT n— top N;LIMIT n OFFSET m— sahifalash- Sahifalashda saralash noyob bo'lsin:
ORDER BY narx, id - Chuqur
OFFSETsekin — katta ro'yxatlarda keyset:WHERE id > oxirgi ORDER BY id LIMIT n FIELD()— o'z tartibingiz bo'yicha saralash
Keyingi dars
12-dars: UPDATE va DELETE — shartlar bilan, xavfli holatlar