Aggregate funksiyalar — COUNT, SUM, AVG, MIN, MAX

~15 daq · MySQL · DML — Ma'lumot Boshqarish

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 qaramaydi
  • COUNT(ustun) — faqat qiymati bor (NULL emas) qatorlarni
  • COUNT(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_BY o'chirilgan serverlarda bu so'rov xato bermaydi — tasodifiy nom ni 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 natija
  • COUNT(ustun) — NULL larni sanamaydi; COUNT(DISTINCT ustun) — noyoblarini
  • Aggregate funksiyalar NULL ni e'tiborsiz qoldiradi
  • Bo'sh to'plamda SUM/AVG — NULL; kerak bo'lsa COALESCE(..., 0)
  • Aggregate bilan oddiy ustunni GROUP BY siz aralashtirib bo'lmaydi
  • SUM(shart) — MySQL da shartli sanash

Keyingi dars

14-dars: GROUP BY va HAVING — guruhlash va filtrlash