Date funksiyalar — NOW, DATE_FORMAT, DATEDIFF, DATE_ADD
Muammodan boshlaylik
Deyarli har bir hisobot vaqtga bog'liq:
- Bugungi buyurtmalar
- O'tgan haftadagi tushum, oyma-oy
- 30 kundan beri faol bo'lmagan mijozlar
- Bugun tug'ilgan kuni bo'lgan mijozlar
- To'lanmagan buyurtma 3 kundan keyin avtomatik bekor bo'lsin
Sana va vaqt bilan to'g'ri ishlash — SQL ning eng amaliy ko'nikmalaridan biri.
Hozirgi vaqt
SELECT NOW(); -- 2026-11-04 14:30:15 — sana va vaqt
SELECT CURDATE(); -- 2026-11-04 — faqat sana
SELECT CURTIME(); -- 14:30:15 — faqat vaqt
SELECT UTC_TIMESTAMP(); -- 2026-11-04 09:30:15 — UTC da
NOW() — sessiya vaqt mintaqasida:
SELECT @@global.time_zone, @@session.time_zone; -- SYSTEM, SYSTEM
SET time_zone = '+05:00'; -- Toshkent
[!TIP] Ko'p loyihalarda qoida: server va baza — UTC, foydalanuvchiga ko'rsatishda — uning mintaqasiga o'giriladi (ilovada). Shunda server boshqa mamlakatga ko'chirilsa ham vaqtlar buzilmaydi.
Qismlarga ajratish
SELECT
YEAR(yaratilgan) AS yil, -- 2026
MONTH(yaratilgan) AS oy, -- 10
DAY(yaratilgan) AS kun, -- 12
HOUR(yaratilgan) AS soat, -- 18
DAYOFWEEK(yaratilgan) AS hafta_kuni, -- 1=yakshanba ... 7=shanba
WEEKDAY(yaratilgan) AS hafta_kuni2, -- 0=dushanba ... 6=yakshanba
QUARTER(yaratilgan) AS chorak, -- 4
DATE(yaratilgan) AS sana -- 2026-10-12
FROM buyurtmalar WHERE id = 2;
Qaysi soatlarda ko'p buyurtma beriladi?
SELECT HOUR(yaratilgan) AS soat, COUNT(*) AS buyurtmalar
FROM buyurtmalar
GROUP BY soat
ORDER BY soat;
Reklamani qachon ishga tushirish kerakligini shu ko'rsatadi.
Formatlash: DATE_FORMAT
SELECT DATE_FORMAT(yaratilgan, '%d.%m.%Y %H:%i') FROM buyurtmalar;
-- 12.10.2026 18:40
| Belgi | Ma'nosi | Misol |
|---|---|---|
%Y |
Yil (4) | 2026 |
%m |
Oy (01–12) | 10 |
%d |
Kun (01–31) | 05 |
%H |
Soat (00–23) | 18 |
%i |
Daqiqa | 40 |
%s |
Soniya | 00 |
%W |
Hafta kuni nomi | Monday |
%M |
Oy nomi | October |
%u |
Hafta raqami | 41 |
Oylik guruhlash uchun:
SELECT DATE_FORMAT(yaratilgan, '%Y-%m') AS oy, COUNT(*)
FROM buyurtmalar
GROUP BY oy;
O'zbekcha oy nomlari uchun — ELT:
SELECT ELT(MONTH(yaratilgan),
'yanvar','fevral','mart','aprel','may','iyun',
'iyul','avgust','sentabr','oktabr','noyabr','dekabr') AS oy
FROM buyurtmalar;
Matndan sanaga — STR_TO_DATE:
SELECT STR_TO_DATE('12.10.2026', '%d.%m.%Y'); -- 2026-10-12
Excel dan kelgan dd.mm.yyyy formatidagi sanalarni import qilishda kerak.
Qo'shish va ayirish
SELECT NOW() + INTERVAL 3 DAY;
SELECT NOW() - INTERVAL 1 MONTH;
SELECT DATE_ADD('2026-01-31', INTERVAL 1 MONTH); -- 2026-02-28 (oy oxiri moslashadi)
SELECT DATE_SUB(CURDATE(), INTERVAL 1 YEAR);
INTERVAL birliklari: SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, YEAR.
Amaliy misollar
-- Oxirgi 7 kundagi buyurtmalar
SELECT * FROM buyurtmalar WHERE yaratilgan >= NOW() - INTERVAL 7 DAY;
-- 3 kundan beri to'lanmagan buyurtmalarni bekor qilish
UPDATE buyurtmalar
SET holat = 'bekor'
WHERE holat = 'yangi' AND yaratilgan < NOW() - INTERVAL 3 DAY;
-- Yetkazib berish sanasi: 2 ish kuni (oddiy variant)
SELECT CURDATE() + INTERVAL 2 DAY;
Farq: DATEDIFF, TIMESTAMPDIFF
SELECT DATEDIFF('2026-12-31', '2026-11-04'); -- 57 — kunlar
DATEDIFF faqat kunlarni beradi. Boshqa birliklar — TIMESTAMPDIFF(birlik, boshi, oxiri):
SELECT TIMESTAMPDIFF(HOUR, '2026-11-01 10:00', '2026-11-04 14:30'); -- 76
SELECT TIMESTAMPDIFF(MONTH, '2026-01-15', '2026-11-04'); -- 9
SELECT TIMESTAMPDIFF(YEAR, '1998-07-21', CURDATE()); -- 28 — yosh
-- Mijozlar: oxirgi buyurtmadan beri necha kun
SELECT m.ism, DATEDIFF(CURDATE(), MAX(b.yaratilgan)) AS kun_oldin
FROM mijozlar m
JOIN buyurtmalar b ON b.mijoz_id = m.id
GROUP BY m.id, m.ism
HAVING kun_oldin > 30; -- "uxlab qolgan" mijozlar
-- Buyurtmadan yetkazishgacha o'rtacha vaqt (soatlarda)
SELECT AVG(TIMESTAMPDIFF(HOUR, yaratilgan, yetkazilgan)) FROM buyurtmalar
WHERE yetkazilgan IS NOT NULL;
Davr boshlari va oxirlari
SELECT LAST_DAY('2026-02-10'); -- 2026-02-28
SELECT DATE_FORMAT(CURDATE(), '%Y-%m-01'); -- joriy oyning 1-kuni
SELECT CURDATE() - INTERVAL WEEKDAY(CURDATE()) DAY; -- joriy haftaning dushanbasi
-- Joriy oydagi buyurtmalar
SELECT COUNT(*) FROM buyurtmalar
WHERE yaratilgan >= DATE_FORMAT(CURDATE(), '%Y-%m-01')
AND yaratilgan < DATE_FORMAT(CURDATE(), '%Y-%m-01') + INTERVAL 1 MONTH;
Muhim: funksiyani ustunga qo'ymang
Bugungi buyurtmalar:
-- ❌ Indeks ishlamaydi — har bir qator uchun DATE() hisoblanadi
SELECT * FROM buyurtmalar WHERE DATE(yaratilgan) = CURDATE();
-- ❌ Indeks ishlamaydi
SELECT * FROM buyurtmalar WHERE YEAR(yaratilgan) = 2026 AND MONTH(yaratilgan) = 10;
-- ✅ Oraliq — indeks ishlaydi
SELECT * FROM buyurtmalar
WHERE yaratilgan >= CURDATE() AND yaratilgan < CURDATE() + INTERVAL 1 DAY;
-- ✅
SELECT * FROM buyurtmalar
WHERE yaratilgan >= '2026-10-01' AND yaratilgan < '2026-11-01';
Natija bir xil, lekin million qatorli jadvalda farq — soniyalar va millisekundlar. Funksiyani ustunga emas, solishtirilayotgan qiymatga qo'llang. Bu "sargable" so'rov deyiladi (34-dars).
Tug'ilgan kunlar
-- Bugun tug'ilgan kuni bo'lganlar
SELECT ism FROM mijozlar
WHERE MONTH(tugilgan_kun) = MONTH(CURDATE())
AND DAY(tugilgan_kun) = DAY(CURDATE());
-- Kelgusi 7 kun ichida
SELECT ism, tugilgan_kun FROM mijozlar
WHERE DATE_FORMAT(tugilgan_kun, '%m%d')
BETWEEN DATE_FORMAT(CURDATE(), '%m%d')
AND DATE_FORMAT(CURDATE() + INTERVAL 7 DAY, '%m%d');
Bu yerda funksiya ustunda — lekin boshqa yo'l yo'q va tug'ilgan kun so'rovlari kam bajariladi. (Dekabr oxirida yil almashinuvini alohida hisobga olish kerak.)
Nima uchun shunday?
Nima uchun DATE(yaratilgan) = CURDATE() indeksdan foydalana olmaydi?
Indeks — yaratilgan qiymatlarining tartiblangan ro'yxati (telefon kitobi kabi). MySQL undan "2026-11-04 00:00 dan 2026-11-05 00:00 gacha" oralig'ini bir zumda topa oladi. Lekin DATE(yaratilgan) qiymatlari indeksda yo'q — ular hisoblanishi kerak. Telefon kitobidan "familiyasining ikkinchi harfi 'a' bo'lganlar" ni qidirish kabi: kitob familiya bo'yicha tartiblangan, lekin bu savol uchun hamma sahifani varaqlash kerak.
Xulosa
Eslab qoling:
NOW(),CURDATE(),UTC_TIMESTAMP()— hozirgi vaqt; mintaqaga e'tibor beringYEAR,MONTH,DAY,HOUR,WEEKDAY— qismlarDATE_FORMAT(d, '%d.%m.%Y')— ko'rsatish;STR_TO_DATE— matndan+ INTERVAL n DAY/DATE_ADD/DATE_SUB— qo'shish/ayirishDATEDIFF— kunlar;TIMESTAMPDIFF(birlik, a, b)— istalgan birlikLAST_DAY— oy oxiriWHEREda ustunni funksiyaga o'ramang —>= boshi AND < oxirioralig'ini ishlating
Keyingi dars
28-dars: Conditional — IF, CASE WHEN, COALESCE, NULLIF, IFNULL