SQL Master πŸ‡ΊπŸ‡Ώ
22 subscribers
1 photo
1 video
56 links
SQL'ni video ko'rib emas, yozib o'rganing. 200+ real masala β€” Uzum, Click, taksi mavzularida. Yozasiz, tizim tekshiradi.

πŸ‘‰ sqlmaster.uz

Admin: @fast_support_admin
Download Telegram
LEFT JOIN yozdingiz, lekin u INNER JOIN bo'lib qoldi πŸ€¦β€β™‚οΈ
Bu β€” SQL suhbatlarida eng ko'p "yiqitadigan" xato.
Vazifa: har bir mijozni va uning yanvardagi buyurtmalari sonini chiqaring. Buyurtma bermaganlar ham ro'yxatda 0 bilan turishi kerak.

Ko'pchilik shunday yozadi πŸ‘‡
SELECT c.name, COUNT(o.id) AS orders
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.created_at >= '2026-01-01'
GROUP BY c.name;

Natija: yanvarda buyurtma bermagan mijozlar umuman yo'qoladi.

Sababi oddiy:
LEFT JOIN avval o'ng jadvaldan mos qator topmasa, o.* ustunlarini NULL qilib qo'yadi. Keyin WHERE o.created_at >= ... ishga tushadi va o'sha NULL qatorlarni o'chirib tashlaydi. Ya'ni siz yozgan LEFT JOIN amalda INNER JOIN.

To'g'ri variant β€” filtrni ON ichiga olish πŸ‘‡
SELECT c.name, COUNT(o.id) AS orders
FROM customers c
LEFT JOIN orders o
ON o.customer_id = c.id
AND o.created_at >= '2026-01-01'
GROUP BY c.name;

πŸ“Œ Yodda tuting:
ON β€” join qilishdan oldin o'ng jadvalni filtrlaydi
WHERE β€” join tugagandan keyin butun natijani filtrlaydi
Va yana bir tuzoq: bu yerda COUNT(*) emas, COUNT(o.id) yozilgan. COUNT(*) buyurtmasi yo'q mijozga ham 1 deb ko'rsatadi, chunki NULL bo'lsa ham qator mavjud.

Shunga o'xshash 200+ masala πŸ‘‰ sqlmaster.uz

Rasmiy kanal: @sqlmasteruz
Marhamat β€” fan-out (dublikat qatorlar) mavzusidagi post:

JOIN dan keyin summangiz 3 barobar oshib ketdimi? πŸ“ˆ
Hisobot yozdingiz, raqam boshliqqa ketdi, keyin ma'lum bo'ldi β€” savdo hajmi aslida uch barobar kam. Tanish holat.
Vazifa: har bir mijoz bo'yicha umumiy buyurtma summasi va sotib olingan mahsulotlar soni.

Ko'pchilik shunday yozadi πŸ‘‡
SELECT c.name,
SUM(o.amount) AS jami_summa,
SUM(i.quantity) AS mahsulotlar
FROM customers c
JOIN orders o ON o.customer_id = c.id
JOIN order_items i ON i.order_id = o.id
GROUP BY c.name;

Muammo: bitta buyurtmada 3 ta mahsulot bo'lsa, JOIN o'sha buyurtmani 3 marta takrorlaydi. Demak o.amount ham 3 marta qo'shiladi.
SUM(o.amount) = xato. SUM(i.quantity) = to'g'ri.
Ya'ni bitta so'rovda bir ustun to'g'ri, ikkinchisi noto'g'ri β€” shuning uchun ham bu xatoni payqash qiyin.

Sabab: JOIN 1:N munosabatda chap jadvalning qatorini ko'paytiradi (fan-out). Agar ikkita 1:N jadval qo'shsangiz β€” qatorlar ko'payib emas, ko'paytirilib ketadi (3 ta mahsulot Γ— 2 ta to'lov = 6 qator).
Yechim: har bir darajani alohida agregatsiya qilib, keyin join qiling πŸ‘‡
WITH ord AS (
SELECT customer_id, SUM(amount) AS jami_summa
FROM orders
GROUP BY customer_id
),
itm AS (
SELECT o.customer_id, SUM(i.quantity) AS mahsulotlar
FROM orders o
JOIN order_items i ON i.order_id = o.id
GROUP BY o.customer_id
)
SELECT c.name, ord.jami_summa, itm.mahsulotlar
FROM customers c
LEFT JOIN ord ON ord.customer_id = c.id
LEFT JOIN itm ON itm.customer_id = c.id;


πŸ” Tekshirish usuli: JOIN dan oldin va keyin COUNT(*) ni solishtiring. Qatorlar soni oshgan bo'lsa β€” join kaliti o'ng jadvalda unikal emas, demak summalaringizga ishonmang.
⚠️ SUM(DISTINCT o.amount) bilan "tuzatmang" β€” ikki mijozning summasi tasodifan teng bo'lsa, bittasi yo'qoladi.

Amaliyot πŸ‘‰ sqlmaster.uz

Rasmiy kanal: @sqlmasteruz
β˜• Ertalabki savol

users jadvalida 100 ta qator bor. Ulardan 30 tasida phone ustuni NULL.

Shu so'rov nima qaytaradi? πŸ‘‡
SELECT COUNT(*), COUNT(phone)
FROM users;


A) 100 va 100
B) 100 va 70
C) 70 va 70

Javobingizni izohda yozing β€” bugun 20:00 da tahlil qilamiz πŸ‘‡

βž–βž–βž–βž–βž–βž–βž–βž–
πŸ’Ύ Amaliyot: sqlmaster.uz
πŸ“’ @sqlmasteruz
⚠️ NOT IN sizni jimgina aldaydi

Vazifa: hech qachon buyurtma bermagan mijozlarni toping.

Ko'pchilik shunday yozadi πŸ‘‡
SELECT name
FROM customers
WHERE id NOT IN (SELECT customer_id FROM orders);


Natija: bo'sh jadval. Bitta ham mijoz chiqmaydi, holbuki ular bor.

Sabab. orders.customer_id ustunida bitta NULL bo'lsa yetarli. id NOT IN (1, 2, NULL) ifodasi hech qachon TRUE bo'lmaydi β€” u UNKNOWN qaytaradi, chunki SQL Β«bu qiymat NULL ga teng emasmi?Β» degan savolga javob bera olmaydi. WHERE esa faqat TRUE qatorlarni o'tkazadi.

To'g'ri variant πŸ‘‡
SELECT c.name
FROM customers c
WHERE NOT EXISTS (
SELECT 1 FROM orders o
WHERE o.customer_id = c.id
);


Yoki LEFT JOIN ... IS NULL orqali:
SELECT c.name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;


πŸ“Œ Qoida: NOT IN faqat ustun NOT NULL ekaniga ishonchingiz komil bo'lsa. Aks holda doim NOT EXISTS.

Bu tuzoq ish suhbatlarida ataylab so'raladi.

🎯 Endi amaliyot: Qora ro'yxatda bo'lmagan mijozlar (NULL tuzog'i)
Aynan shu tuzoq ustiga qurilgan masala. NOT EXISTS bilan yozib ko'ring πŸ‘‡

βž–βž–βž–βž–βž–βž–βž–βž–
πŸ’Ύ Amaliyot: sqlmaster.uz
πŸ“’ @sqlmasteruz
βœ… Ertalabki savol javobi: B β€” 100 va 70

COUNT(*) qatorlarni sanaydi β€” 100 ta.
COUNT(phone) esa faqat NULL bo'lmagan qiymatlarni sanaydi β€” 70 ta.

Bu farq hisobotlarda jimgina xato keltirib chiqaradi.

πŸ“Š Yodda tuting:
COUNT(*) β€” qatorlar soni
COUNT(ustun) β€” NULL bo'lmagan qiymatlar soni
COUNT(1) β€” COUNT(*) bilan bir xil, tezligi ham bir xil
COUNT(DISTINCT ustun) β€” takrorlanmaydigan qiymatlar

⚠️ Xuddi shu mantiq AVG va SUM ga ham tegishli:
SELECT AVG(salary) FROM employees;

Maoshi kiritilmagan (NULL) xodimlar o'rtachaga umuman qo'shilmaydi. Ularni nol deb hisoblamoqchi bo'lsangiz:
SELECT AVG(COALESCE(salary, 0)) FROM employees;

Ikki so'rov ikki xil raqam qaytaradi β€” qaysi biri to'g'ri ekanini siz hal qilasiz, baza emas.

πŸ’¬ Shu xatoga duch kelganmisiz? Izohda yozing.

🎯 Endi amaliyot: O'rtacha: NULL larni hisobga olish
O'qib tushundingiz β€” endi o'zingiz yozib ko'ring πŸ‘‡

βž–βž–βž–βž–βž–βž–βž–βž–
πŸ’Ύ Amaliyot: sqlmaster.uz
πŸ“’ @sqlmasteruz
status ustunida NULL qatorlar bor. Β«SELECT * FROM tasks WHERE status <> 'active'Β» β€” o'sha NULL qatorlar natijaga chiqadimi?
Anonymous Quiz
0%
Ha, chiqadi
100%
Yo'q, chiqmaydi
0%
Bazaga bog'liq
πŸ”₯1
πŸ”’ SQL so'rovi siz yozgan tartibda bajarilmaydi

Siz SELECT dan boshlab yozasiz, baza esa boshqa tartibda ishlaydi:

1️⃣ FROM va JOIN β€” jadvallar birlashtiriladi
2️⃣ WHERE β€” qatorlar filtrlanadi
3️⃣ GROUP BY β€” guruhlanadi
4️⃣ HAVING β€” guruhlar filtrlanadi
5️⃣ SELECT β€” ustunlar tanlanadi, alias shu yerda paydo bo'ladi
6️⃣ ORDER BY β€” saralanadi
7️⃣ LIMIT β€” kesiladi

Shundan kelib chiqadigan uchta amaliy xulosa:

❌ WHERE da alias ishlatib bo'lmaydi β€” u hali mavjud emas:
SELECT price * 1.12 AS total
FROM products
WHERE total > 100; -- xato!

βœ… To'g'risi: WHERE price * 1.12 > 100

βœ… ORDER BY da esa alias ishlaydi β€” u SELECT dan keyin bajariladi.

❌ WHERE ichida SUM() yozib bo'lmaydi β€” guruhlash hali bo'lmagan. Agregat bo'yicha filtr faqat HAVING da:
SELECT customer_id, SUM(amount) AS jami
FROM orders
WHERE status = 'paid' -- qatorlarni filtrlaydi
GROUP BY customer_id
HAVING SUM(amount) > 1000000; -- guruhlarni filtrlaydi


πŸ“Œ Qoida: WHERE β€” guruhlashdan oldin, HAVING β€” keyin. Filtrni iloji boricha WHERE ga qo'ying: kamroq qator guruhlanadi, so'rov tezroq ishlaydi.

🎯 Endi amaliyot: HAVING ichida subquery
O'qib tushundingiz β€” endi o'zingiz yozib ko'ring πŸ‘‡

βž–βž–βž–βž–βž–βž–βž–βž–
πŸ’Ύ Amaliyot: sqlmaster.uz
πŸ“’ @sqlmasteruz
πŸ‘1
βœ… Ertalabki test javobi: NULL qatorlar chiqmaydi

SQL ikki qiymatli emas, uch qiymatli mantiq bilan ishlaydi: TRUE, FALSE va UNKNOWN.

NULL <> 'active' β†’ UNKNOWN
NULL = NULL β†’ UNKNOWN (ha, NULL o'ziga ham teng emas!)

WHERE esa faqat TRUE bo'lgan qatorlarni o'tkazadi. UNKNOWN β€” tashlab yuboriladi.

Yechimlar:
-- 1. Ochiq-oydin qo'shish
WHERE status <> 'active' OR status IS NULL

-- 2. NULL ni qiymatga aylantirish
WHERE COALESCE(status, 'none') <> 'active'

-- 3. PostgreSQL usuli
WHERE status IS DISTINCT FROM 'active'


Uchinchisi eng toza: IS DISTINCT FROM NULL ni oddiy qiymat kabi solishtiradi.

⚠️ Eng xavflisi shundaki, bunday so'rov xato bermaydi. Shunchaki qatorlar yo'qoladi β€” hisobotdagi raqam kamayadi, siz esa sezmaysiz.

πŸ’¬ Sizning bazangizda qaysi ustunlar NULL bo'lishi mumkin? Bir tekshirib ko'ring πŸ‘‡

🎯 Endi amaliyot: NULL: uch qiymatli mantiq tuzog'i
O'qib tushundingiz β€” endi o'zingiz yozib ko'ring πŸ‘‡

βž–βž–βž–βž–βž–βž–βž–βž–
πŸ’Ύ Amaliyot: sqlmaster.uz
πŸ“’ @sqlmasteruz
β˜• Ertalabki masala: klassik intervyu savoli

Jadval: employees(id, name, department, salary)

Vazifa: har bir bo'limdagi eng yuqori maosh oladigan xodimni chiqaring. Bitta bo'limda bir xil maosh bilan ikki kishi bo'lsa β€” ikkalasi ham ro'yxatda bo'lsin.

SELECT ???
FROM employees
???


🎯 Bu savol ish suhbatlarida eng ko'p beriladigan uchlikdan biri. Kamida ikki xil yechimi bor.

✍️ O'z variantingizni izohda yozing β€” 20:00 da ikkala yechimni ham tahlil qilamiz πŸ‘‡

🎯 Endi amaliyot: Har bo'limdagi eng yuqori maosh
Masala saytda ham bor β€” yozing, tizim javobingizni darhol tekshiradi πŸ‘‡

βž–βž–βž–βž–βž–βž–βž–βž–
πŸ’Ύ Amaliyot: sqlmaster.uz
πŸ“’ @sqlmasteruz
πŸͺŸ ROW_NUMBER, RANK, DENSE_RANK β€” farqi nimada?

Uchalasi ham qatorlarga raqam beradi, lekin teng qiymatlarda boshqacha yo'l tutadi.

Misol: ballar 100, 90, 90, 80

ROW_NUMBER() β†’ 1, 2, 3, 4
Har qatorga noyob raqam. Teng bo'lsa ham farqlaydi (qaysi biri 2, qaysi biri 3 β€” tasodifiy, agar ORDER BY aniq bo'lmasa).

RANK() β†’ 1, 2, 2, 4
Tenglar bir xil o'rin oladi, keyingi o'rin sakraydi. Sport natijalari shunday.

DENSE_RANK() β†’ 1, 2, 2, 3
Tenglar bir xil o'rin oladi, sakrash yo'q.

SELECT
name,
score,
ROW_NUMBER() OVER (ORDER BY score DESC) AS rn,
RANK() OVER (ORDER BY score DESC) AS rnk,
DENSE_RANK() OVER (ORDER BY score DESC) AS drnk
FROM results;


PARTITION BY β€” guruh ichida sanash uchun:
ROW_NUMBER() OVER (
PARTITION BY department
ORDER BY salary DESC
)

Bu Β«har bo'lim ichida maosh bo'yicha tartiblab, 1 dan sanashΒ» degani.

πŸ“Œ Qaysi birini tanlash:
β€’ dublikat o'chirish, Β«har guruhdan bittasiΒ» β†’ ROW_NUMBER
β€’ Β«top 3Β», tenglar ham kirsin β†’ DENSE_RANK
β€’ haqiqiy reyting, o'rin sakrasin β†’ RANK

🎯 Endi amaliyot: RANK va DENSE_RANK farqi
O'qib tushundingiz β€” endi o'zingiz yozib ko'ring πŸ‘‡

βž–βž–βž–βž–βž–βž–βž–βž–
πŸ’Ύ Amaliyot: sqlmaster.uz
πŸ“’ @sqlmasteruz
βœ… Ertalabki masala yechimi: har bo'limdagi eng yuqori maosh

1-usul: window funksiya (zamonaviy, tavsiya etiladi)
WITH ranked AS (
SELECT name, department, salary,
RANK() OVER (PARTITION BY department
ORDER BY salary DESC) AS r
FROM employees
)
SELECT name, department, salary
FROM ranked
WHERE r = 1;

Bu yerda RANK ishlatildi, chunki shartda Β«bir xil maosh bo'lsa ikkalasi hamΒ» deyilgan. ROW_NUMBER bo'lsa faqat bittasi chiqardi.

2-usul: korrelyatsion subquery (eski bazalarda ham ishlaydi)
SELECT name, department, salary
FROM employees e
WHERE salary = (
SELECT MAX(salary)
FROM employees
WHERE department = e.department
);


Qaysi biri yaxshi? Odatda window β€” jadval bir marta o'qiladi. Subquery esa har qator uchun ichki so'rovni qayta bajarishi mumkin (index bo'lmasa ayniqsa og'ir).

❌ Eng ko'p uchraydigan xato:
SELECT name, department, MAX(salary)
FROM employees
GROUP BY department; -- xato!

Bu yerda name qaysi xodimniki ekani noma'lum. PostgreSQL xato beradi, MySQL esa tasodifiy ism qaytaradi β€” bu yanada yomon, chunki so'rov Β«ishlaydiΒ».

πŸ’¬ Siz qaysi usulni yozgan edingiz?

🎯 Endi amaliyot: Ikkinchi eng yuqori maosh
Shu mantiqning davomi β€” intervyu klassikasi πŸ‘‡

βž–βž–βž–βž–βž–βž–βž–βž–
πŸ’Ύ Amaliyot: sqlmaster.uz
πŸ“’ @sqlmasteruz
Ballar: 100, 90, 90, 80. RANK() OVER (ORDER BY score DESC) bo'yicha 80 ballning o'rni nechchi bo'ladi?
Anonymous Quiz
20%
3
60%
4
20%
2
πŸ” DISTINCT bilan Β«tuzatishΒ» β€” eng qimmat odat

So'rov dublikat qaytardi. Ko'pchilik shu zahoti DISTINCT qo'shadi va davom etadi.

SELECT DISTINCT c.name, o.amount
FROM customers c
JOIN orders o ON o.customer_id = c.id;


Muammo: DISTINCT sababni emas, alomatni yashiradi. Dublikat paydo bo'lgan bo'lsa, demak JOIN kaliti o'ng jadvalda unikal emas. Va agar ikki mijozning summasi tasodifan teng bo'lsa β€” DISTINCT ulardan birini o'chirib tashlaydi. Hisobot jimgina noto'g'ri bo'ladi.

Avval dublikat borligini tekshiring:
SELECT email, COUNT(*)
FROM users
GROUP BY email
HAVING COUNT(*) > 1;


Dublikat qatorlarni o'chirish (eng ishonchli usul β€” ROW_NUMBER):
WITH d AS (
SELECT id,
ROW_NUMBER() OVER (PARTITION BY email
ORDER BY created_at) AS rn
FROM users
)
DELETE FROM users
WHERE id IN (SELECT id FROM d WHERE rn > 1);

Bu har bir email uchun eng eskisini qoldiradi, qolganini o'chiradi.

⚠️ DELETE yozishdan oldin doim shu so'rovni SELECT bilan bir marta ishga tushiring β€” nima o'chishini ko'ring.

πŸ“Œ DISTINCT yozgingiz kelsa, avval bitta savol bering: bu dublikat qayerdan keldi?

🎯 Endi amaliyot: Takrorlangan email larni topish
O'qib tushundingiz β€” endi o'zingiz yozib ko'ring πŸ‘‡

βž–βž–βž–βž–βž–βž–βž–βž–
πŸ’Ύ Amaliyot: sqlmaster.uz
πŸ“’ @sqlmasteruz
βœ… Ertalabki test javobi: 4-o'rin

RANK() tenglardan keyin o'rinni sakratadi: 1, 2, 2, 4. Uchinchi o'rin umuman bo'lmaydi.
DENSE_RANK() esa sakratmaydi: 1, 2, 2, 3.

Amalda bu qayerda muhim?

Vazifa: Β«top 3 mahsulotΒ» ro'yxatini chiqaring.

-- DENSE_RANK: teng natijalar ham kiradi
WHERE drnk <= 3 -- 3 ta o'rin, lekin 4-5 qator bo'lishi mumkin

-- ROW_NUMBER: qat'iy 3 qator
WHERE rn <= 3


Agar boshliq Β«menga aniq 3 qator kerakΒ» desa β€” ROW_NUMBER. Agar Β«uchinchi o'rinni bo'lishganlar ham chiqsinΒ» desa β€” DENSE_RANK.

Bu texnik emas, biznes savoli. Shuning uchun analitik so'rov yozishdan oldin aniqlab oladi.

πŸ’¬ Sizning ishingizda Β«top NΒ» qanday hisoblanadi?

🎯 Endi amaliyot: Takroriy yozuvlarni tozalash
O'qib tushundingiz β€” endi o'zingiz yozib ko'ring πŸ‘‡

βž–βž–βž–βž–βž–βž–βž–βž–
πŸ’Ύ Amaliyot: sqlmaster.uz
πŸ“’ @sqlmasteruz
β˜• Ertalabki masala: ketma-ket kunlar

Jadval: logins(user_id, login_date) β€” har bir kirish bitta qator.

Vazifa: kamida 3 kun ketma-ket tizimga kirgan foydalanuvchilarni toping.

Masalan:
β€’ user 1 β†’ 5, 6, 7-oktabr βœ…
β€’ user 2 β†’ 5, 6, 8-oktabr ❌

SELECT user_id
FROM logins
???


⚠️ Ogohlantirish: bu masala GROUP BY bilan yechilmaydi. Bu yerda boshqa usul kerak.

🎯 Bu «gaps and islands» deb ataladigan klassik masala. Uni bilgan odam intervyuda darrov ajralib turadi.

✍️ Fikringizni izohda yozing, 13:00 da to'liq tahlil qilamiz πŸ‘‡

🎯 Endi amaliyot: 3+ ketma-ket kun kirgan foydalanuvchilar
Masala saytda tayyor turibdi β€” urinib ko'ring πŸ‘‡

βž–βž–βž–βž–βž–βž–βž–βž–
πŸ’Ύ Amaliyot: sqlmaster.uz
πŸ“’ @sqlmasteruz
🏝 Gaps and islands: ketma-ketlikni qanday topish kerak

Ertalabki masalaning yechimi. Butun sir bitta hiylada.

Hiyla: agar sanalar ketma-ket bo'lsa, ularning tartib raqami ham ketma-ket o'sadi. Demak sana βˆ’ tartib_raqami ayirmasi bitta Β«orolchaΒ» ichida o'zgarmaydi.

WITH t AS (
SELECT user_id, login_date,
login_date - (ROW_NUMBER() OVER (
PARTITION BY user_id
ORDER BY login_date
) * INTERVAL '1 day') AS grp
FROM (SELECT DISTINCT user_id, login_date FROM logins) x
)
SELECT user_id
FROM t
GROUP BY user_id, grp
HAVING COUNT(*) >= 3;


Nima bo'lyapti?
5, 6, 7-oktabr β†’ raqamlari 1, 2, 3 β†’ ayirma har uchalasida bir xil β†’ bitta guruh, 3 qator β†’ shart bajarildi.
5, 6, 8-oktabr β†’ 8 da ayirma o'zgaradi β†’ yangi guruh boshlanadi β†’ hech qaysi guruhda 3 ta yo'q.

⚠️ SELECT DISTINCT shart: bitta kunda ikki marta kirgan bo'lsa, raqamlar siljib ketadi va natija buziladi.

πŸ“Œ Xuddi shu usul boshqa joylarda ham ishlaydi:
β€’ streak hisoblash (ketma-ket kunlar)
β€’ uzluksiz ishlagan davrlar
β€’ sensor ma'lumotlaridagi uzilishlar
β€’ abonement to'lovlaridagi bo'shliqlar

πŸ’¬ Bu usulni bilarmidingiz? Boshqa yechim taklif qila olasizmi?

🎯 Endi amaliyot: Eng uzun g'alabalar seriyasi
Xuddi shu usul bilan yechiladi β€” mustahkamlab oling πŸ‘‡

βž–βž–βž–βž–βž–βž–βž–βž–
πŸ’Ύ Amaliyot: sqlmaster.uz
πŸ“’ @sqlmasteruz
πŸ‘1
🎯 SQL ni o'qib emas, yozib o'rganasiz

Bugungi Β«gaps and islandsΒ» masalasini o'qib chiqdingiz. Tushundingiz. Endi rostini aytaylik: bir haftadan keyin uni o'zingiz noldan yoza olasizmi?

Ko'pchilik yoza olmaydi. Chunki o'qish β€” tanish tuyg'usi beradi, ko'nikma bermaydi. Ko'nikma faqat bo'sh oynaga so'rov yozib, xato olib, tuzatib paydo bo'ladi.

Shuning uchun sqlmaster.uz qurildi:

πŸ”Ή 195 ta masala β€” SELECT asoslaridan window funksiya va CTE gacha
πŸ”Ή Real schemalar β€” Uzum, Click, taksi, bank jadvallari. O'quv misollari emas, ishdagi vaziyatlar
πŸ”Ή Yozasiz β€” tizim darrov tekshiradi. To'g'ri javobni emas, sizning so'rovingiz natijasini solishtiradi
πŸ”Ή Muhokama bo'limi β€” boshqalarning yechimini ko'rasiz. Bitta masalaning 5 xil yechimi bo'ladi
πŸ”Ή Bosqichma-bosqich β€” Oson β†’ O'rtacha β†’ Qiyin

πŸ’‘ Birinchi 50 ta masala mutlaqo bepul. Ro'yxatdan o'tish 30 soniya, karta kerak emas.

Bugun 3 ta masala yeching. Ertaga yana 3 ta. Bir oydan keyin intervyuda Β«JOIN yozib beringΒ» degan gap sizni cho'chitmaydi.

βž–βž–βž–βž–βž–βž–βž–βž–
πŸ’Ύ Amaliyot: sqlmaster.uz
πŸ“’ @sqlmasteruz
β˜• Ertalabki savol: qaysi biri tezroq?

Ikkala so'rov ham bir xil natija beradi β€” buyurtma bergan mijozlar ro'yxati.

-- 1-variant
SELECT * FROM customers c
WHERE c.id IN (SELECT customer_id FROM orders);

-- 2-variant
SELECT * FROM customers c
WHERE EXISTS (
SELECT 1 FROM orders o
WHERE o.customer_id = c.id
);


Sizningcha qaysi biri tezroq ishlaydi?

A) IN tezroq
B) EXISTS tezroq
C) Farqi yo'q

✍️ Javobingizni izohda yozing. Kechqurun 20:00 da query plan bilan ko'rsataman πŸ‘‡

βž–βž–βž–βž–βž–βž–βž–βž–
πŸ’Ύ Amaliyot: sqlmaster.uz
πŸ“’ @sqlmasteruz
🐌 Index bor, lekin so'rov sekin. Nega?

Index yaratilgan bo'lsa ham, baza uni ishlatmasligi mumkin. Mana eng ko'p uchraydigan 5 holat:

1️⃣ Ustunga funksiya qo'llansa
WHERE DATE(created_at) = '2026-10-06'   -- index ishlamaydi
WHERE created_at >= '2026-10-06'
AND created_at < '2026-10-07' -- index ishlaydi

Index created_at qiymatlarini saqlaydi, DATE(created_at) natijasini emas.

2️⃣ LIKE boshida foiz bo'lsa
LIKE 'Ali%' β€” ishlaydi
LIKE '%Ali' β€” ishlamaydi (index alifbo tartibida, boshi noma'lum)

3️⃣ Tip mos kelmasa
WHERE phone = 998901234567 β€” phone matn ustuni bo'lsa, baza har qatorni songa aylantiradi va index chetda qoladi. Tirnoq qo'ying.

4️⃣ OR ishlatilsa
WHERE a = 1 OR b = 2 β€” ko'pincha to'liq skan. UNION ALL bilan ikki so'rovga bo'lish tezroq bo'lishi mumkin.

5️⃣ Jadval kichik bo'lsa
1000 qatorli jadvalda to'liq o'qish indexdan tez. Bu xato emas β€” optimizator to'g'ri qaror qilyapti.

πŸ“Œ Taxmin qilmang, tekshiring:
EXPLAIN ANALYZE
SELECT ...;

Natijada Seq Scan ko'rsangiz β€” index ishlamayapti. Index Scan yoki Bitmap Index Scan ko'rsangiz β€” ishlayapti.

βž–βž–βž–βž–βž–βž–βž–βž–
πŸ’Ύ Amaliyot: sqlmaster.uz
πŸ“’ @sqlmasteruz
βœ… Javob: C β€” zamonaviy bazalarda farqi deyarli yo'q

PostgreSQL va SQL Server optimizatori IN va EXISTS ni ko'pincha bir xil planga aylantiradi (semi-join). Ya'ni Β«EXISTS doim tezroqΒ» degan eski maslahat bugun har doim ham to'g'ri emas.

Lekin ikkita muhim farq bor πŸ‘‡

1️⃣ NULL bilan xulq-atvor. NOT IN ichida bitta NULL bo'lsa, natija butunlay bo'sh chiqadi. NOT EXISTS da bunday muammo yo'q. Shuning uchun inkorda doim NOT EXISTS.

2️⃣ Ichki ro'yxat katta bo'lsa. IN (1, 2, 3, ... 10000) ko'rinishidagi qo'lda yozilgan uzun ro'yxat sekin ishlaydi β€” vaqtinchalik jadval yoki JOIN afzal.

Uchinchi variant β€” JOIN:
SELECT DISTINCT c.*
FROM customers c
JOIN orders o ON o.customer_id = c.id;

⚠️ Bu yerda DISTINCT kerak bo'ldi, chunki mijozning 5 ta buyurtmasi bo'lsa 5 marta chiqadi. EXISTS da bu muammo yo'q β€” u Β«bormi?Β» degan savolga javob beradi, ko'paytirmaydi.

πŸ“Œ Xulosa: Β«bor-yo'qliginiΒ» tekshirish uchun β€” EXISTS. Ustun kerak bo'lsa β€” JOIN.

πŸ’¬ EXPLAIN ANALYZE ni ishlatib ko'rganmisiz?

🎯 Endi amaliyot: EXISTS va IN β€” qayta yozish
O'qib tushundingiz β€” endi o'zingiz yozib ko'ring πŸ‘‡

βž–βž–βž–βž–βž–βž–βž–βž–
πŸ’Ύ Amaliyot: sqlmaster.uz
πŸ“’ @sqlmasteruz