Aggregate funksiyalar — COUNT, SUM, AVG, MIN, MAX
Muammodan boshlaylik
Do'kon egasi har kuni ertalab bir xil savollar beradi:
- Omborda jami nechta mahsulot turi bor?
- Ombordagi tovarlarning umumiy qiymati qancha?
- O'rtacha mahsulot narxi?
- Eng qimmat va eng arzon mahsulot?
Bularning hammasi ko'p qatordan bitta javob chiqarish. SQL da buning uchun aggregate (yig'uvchi) funksiyalar bor.
Beshta asosiy funksiya
SELECT
COUNT(*) AS mahsulot_turlari,
SUM(soni) AS jami_dona,
SUM(narx * soni) AS ombor_qiymati,
ROUND(AVG(narx)) AS ortacha_narx,
MIN(narx) AS eng_arzon,
MAX(narx) AS eng_qimmat
FROM mahsulotlar;
+------------------+-----------+---------------+--------------+-----------+------------+
| mahsulot_turlari | jami_dona | ombor_qiymati | ortacha_narx | eng_arzon | eng_qimmat |
+------------------+-----------+---------------+--------------+-----------+------------+
| 7 | 219 | 290700000 | 6445714 | 120000 | 16900000 |
+------------------+-----------+---------------+--------------+-----------+------------+
7 ta qator → 1 ta natija qatori.
| Funksiya | Nima qiladi |
|---|---|
COUNT(*) |
Qatorlar soni |
COUNT(ustun) |
NULL bo'lmagan qiymatlar soni |
COUNT(DISTINCT ustun) |
Takrorlanmas qiymatlar soni |
SUM(ustun) |
Yig'indi |
AVG(ustun) |
O'rtacha |
MIN(ustun) / MAX(ustun) |
Eng kichik / eng katta |
COUNT ning uch xili
SELECT
COUNT(*) AS jami_mijozlar, -- 4
COUNT(telefon) AS telefoni_borlar, -- 3 (Jasurniki NULL)
COUNT(DISTINCT shahar) AS shaharlar_soni -- 3
FROM mijozlar;
COUNT(*)— qatorlarni sanaydi, ichida nima borligiga qaramaydiCOUNT(ustun)— faqat qiymati bor (NULLemas) qatorlarniCOUNT(DISTINCT ustun)— har xil qiymatlarni
COUNT(*) va COUNT(1) — bir xil, tezligi ham bir xil. COUNT(*) ni yozing.
WHERE bilan birga
WHERE avval qatorlarni filtrlaydi, keyin aggregate hisoblanadi:
-- Telefonlar toifasidagi mahsulotlar
SELECT COUNT(*), AVG(narx) FROM mahsulotlar WHERE toifa_id = 1;
-- Oktabrdagi buyurtmalar soni
SELECT COUNT(*) FROM buyurtmalar
WHERE yaratilgan >= '2026-10-01' AND yaratilgan < '2026-11-01';
-- Barcha yetkazilgan buyurtmalardan tushum
SELECT SUM(q.soni * q.narx) AS tushum
FROM buyurtma_qatorlari q
JOIN buyurtmalar b ON b.id = q.buyurtma_id
WHERE b.holat = 'yetkazildi';
-- 25040000
NULL va aggregate funksiyalar
Barcha aggregate funksiyalar (COUNT(*) dan tashqari) NULL larni e'tiborsiz qoldiradi.
CREATE TABLE baholar (talaba VARCHAR(50), ball INT NULL);
INSERT INTO baholar VALUES ('Ali', 80), ('Vali', 100), ('Sami', NULL);
SELECT AVG(ball) FROM baholar; -- 90.0000 — (80 + 100) / 2
SELECT SUM(ball) / COUNT(*) FROM baholar; -- 60.0000 — (80 + 100) / 3
Qaysi biri to'g'ri? Sami imtihonga kelmagan bo'lsa (NULL — noma'lum) — 90. Agar kelmaslik — nol ball degani bo'lsa — 60. Biznes qoidasini bilish kerak. NULL ni nol deb hisoblash uchun:
SELECT AVG(COALESCE(ball, 0)) FROM baholar; -- 60.0000
Bo'sh to'plam
SELECT COUNT(*), SUM(narx), AVG(narx) FROM mahsulotlar WHERE narx > 999999999;
-- 0, NULL, NULL
Hech qanday qator topilmasa: COUNT — 0, boshqalari — NULL (nol emas!). Ilovada hisob-kitobdan oldin:
SELECT COALESCE(SUM(narx), 0) FROM mahsulotlar WHERE narx > 999999999; -- 0
COALESCE — birinchi NULL bo'lmagan qiymatni qaytaradi (28-dars).
Yaxlitlash
SELECT ROUND(AVG(narx)) FROM mahsulotlar; -- 6445714
SELECT ROUND(AVG(narx), 2) FROM mahsulotlar; -- 6445714.29
SELECT FORMAT(AVG(narx), 0) FROM mahsulotlar; -- '6,445,714' — matn!
FORMAT() natijasi — matn, son emas. Faqat ko'rsatish uchun.
Aggregate va oddiy ustunlarni aralashtirish
SELECT nom, MAX(narx) FROM mahsulotlar;
-- ERROR 1140: In aggregated query without GROUP BY, expression #1 of SELECT list
-- contains nonaggregated column 'dokon.mahsulotlar.nom'
Mantiqan: MAX(narx) — bitta son. nom esa 7 ta. Qaysi nom ni ko'rsatish kerak? MySQL bilmaydi va to'g'ri qilib xato beradi.
"Eng qimmat mahsulot nomi" ni topishning to'g'ri yo'llari:
-- 1. Saralash
SELECT nom, narx FROM mahsulotlar ORDER BY narx DESC LIMIT 1;
-- 2. Subquery (21-dars)
SELECT nom, narx FROM mahsulotlar WHERE narx = (SELECT MAX(narx) FROM mahsulotlar);
Ikkinchisi bir xil narxli bir nechta mahsulot bo'lsa — hammasini qaytaradi.
[!INFO] Eski MySQL versiyalarida yoki
ONLY_FULL_GROUP_BYo'chirilgan serverlarda bu so'rov xato bermaydi — tasodifiynomni qaytaradi. Natija ishonchsiz, lekin hech qanday ogohlantirish yo'q. Shuning uchun bu rejimni o'chirmang.
Shartli hisoblash
Bitta so'rovda turli shartlar bo'yicha sanash:
SELECT
COUNT(*) AS jami,
SUM(holat = 'yetkazildi') AS yetkazilgan,
SUM(holat = 'bekor') AS bekor,
SUM(holat IN ('yangi', 'tolangan', 'yolda')) AS jarayonda
FROM buyurtmalar;
+------+-------------+-------+-----------+
| jami | yetkazilgan | bekor | jarayonda |
+------+-------------+-------+-----------+
| 5 | 2 | 1 | 2 |
+------+-------------+-------+-----------+
MySQL da holat = 'bekor' — 1 yoki 0. Ularning yig'indisi — mos kelganlar soni. Standart SQL da xuddi shu ish CASE bilan qilinadi (28-dars).
Nima uchun shunday?
Nima uchun "jami summa" ni har safar SUM() bilan hisoblaymiz — uni alohida ustunda saqlab qo'ysak tezroq emasmi?
Saqlangan jami — bu ikkinchi haqiqat manbai. Buyurtma qatori qo'shilsa, o'zgarsa yoki o'chirilsa — jamini ham yangilashni unutmaslik kerak. Bitta joyda unutildi — va hisobotlar asl ma'lumotdan farq qila boshlaydi. SUM() esa doim haqiqiy ma'lumotdan hisoblaydi. Saqlangan jami faqat haqiqatan sekin bo'lganda — ataylab tanlanadigan optimizatsiya (47-dars, denormalizatsiya).
Xulosa
Eslab qoling:
COUNT(*),SUM,AVG,MIN,MAX— ko'p qatordan bitta natijaCOUNT(ustun)—NULLlarni sanamaydi;COUNT(DISTINCT ustun)— noyoblarini- Aggregate funksiyalar
NULLni e'tiborsiz qoldiradi - Bo'sh to'plamda
SUM/AVG—NULL; kerak bo'lsaCOALESCE(..., 0) - Aggregate bilan oddiy ustunni
GROUP BYsiz aralashtirib bo'lmaydi SUM(shart)— MySQL da shartli sanash
Keyingi dars
14-dars: GROUP BY va HAVING — guruhlash va filtrlash