Tarih Fonksiyonları: NOW, DATE_FORMAT, DATEDIFF
Giriş — Zamanla Çalışmak
E-ticaret sitesinde tarihlerle sürekli çalışırsın: "Son 30 gündeki siparişler", "Bu ayki satışlar", "Müşterinin hesap yaşı", "Siparişin kargoya verilmesi kaç gün sürdü?"... Tarih fonksiyonları SQL'in en kullanışlı araçlarından biridir.
🎯 Analoji: Tarih fonksiyonlarını bir takvim uygulaması gibi düşün. Bugünün tarihini alabilir, iki tarih arasındaki farkı hesaplayabilir, tarihe gün/ay/yıl ekleyebilir, tarihin sadece yıl veya ay kısmını çıkarabilirsin.
Mevcut Tarih ve Zaman
-- Şu anki tarih ve saat
SELECT NOW(); -- 2024-01-15 14:30:45
SELECT CURRENT_TIMESTAMP(); -- Aynı şey
-- Sadece tarih
SELECT CURDATE(); -- 2024-01-15
SELECT CURRENT_DATE(); -- Aynı şey
-- Sadece saat
SELECT CURTIME(); -- 14:30:45
SELECT CURRENT_TIME(); -- Aynı şey
-- UNIX timestamp (epoch)
SELECT UNIX_TIMESTAMP(); -- 1705322245
SELECT FROM_UNIXTIME(1705322245); -- 2024-01-15 14:30:45DATEDIFF ve TIMESTAMPDIFF — Tarih Farkı
DATEDIFF — Gün Farkı
DATEDIFF(tarih1, tarih2) -- tarih1 - tarih2 = gün farkı
SELECT DATEDIFF('2024-12-31', '2024-01-01'); -- 365
SELECT DATEDIFF('2024-01-01', '2024-12-31'); -- -365 (negatif)
-- Siparişin kaç gün önce verildiği
SELECT order_id, order_date,
DATEDIFF(NOW(), order_date) AS days_ago
FROM orders
ORDER BY days_ago ASC;
-- Müşterinin hesap yaşı (gün)
SELECT first_name, registration_date,
DATEDIFF(CURDATE(), registration_date) AS account_age_days
FROM customers;TIMESTAMPDIFF — Esnek Zaman Farkı
TIMESTAMPDIFF(birim, başlangıç, bitiş)
-- Yıl farkı
SELECT TIMESTAMPDIFF(YEAR, '1990-05-15', CURDATE()) AS age;
-- 33 (veya 34, tarihe göre)
-- Ay farkı
SELECT TIMESTAMPDIFF(MONTH, '2024-01-01', '2024-06-15'); -- 5
-- Saat farkı
SELECT TIMESTAMPDIFF(HOUR, order_date, NOW()) AS hours_since_order
FROM orders;
-- Sipariş işleme süresi (saat)
SELECT order_id,
TIMESTAMPDIFF(HOUR, order_date, updated_at) AS processing_hours
FROM orders WHERE status = 'shipped';Birimler: YEAR, QUARTER, MONTH, WEEK, DAY, HOUR, MINUTE, SECOND
DATE_ADD ve DATE_SUB — Tarihe Ekleme/Çıkarma
-- 30 gün sonrası
SELECT DATE_ADD(CURDATE(), INTERVAL 30 DAY);
-- 3 ay öncesi
SELECT DATE_SUB(NOW(), INTERVAL 3 MONTH);
-- 1 yıl ve 6 ay sonrası
SELECT DATE_ADD(CURDATE(), INTERVAL 18 MONTH);
-- Alternatif syntax (+ INTERVAL)
SELECT CURDATE() + INTERVAL 30 DAY;
SELECT NOW() - INTERVAL 3 MONTH;E-ticaret kullanım senaryoları:
-- Son 7 gündeki siparişler
SELECT * FROM orders WHERE order_date >= DATE_SUB(NOW(), INTERVAL 7 DAY);
-- Son 30 gündeki siparişler
SELECT * FROM orders WHERE order_date >= NOW() - INTERVAL 30 DAY;
-- Bu ayki siparişler
SELECT * FROM orders
WHERE order_date >= DATE_FORMAT(NOW(), '%Y-%m-01')
AND order_date < DATE_ADD(DATE_FORMAT(NOW(), '%Y-%m-01'), INTERVAL 1 MONTH);
-- Tahmini teslimat tarihi (5 iş günü sonra ≈ 7 gün)
SELECT order_id, order_date,
DATE_ADD(order_date, INTERVAL 7 DAY) AS estimated_delivery
FROM orders WHERE status = 'shipped';
-- Üyelik sona erme tarihi (1 yıl)
SELECT first_name,
registration_date,
DATE_ADD(registration_date, INTERVAL 1 YEAR) AS membership_expires
FROM customers;INTERVAL birimleri: YEAR, MONTH, WEEK, DAY, HOUR, MINUTE, SECOND, QUARTER
EXTRACT — Tarih Parçalarını Çıkarma
-- Yıl
SELECT EXTRACT(YEAR FROM '2024-06-15'); -- 2024
SELECT YEAR('2024-06-15'); -- 2024 (kısa yol)
-- Ay
SELECT EXTRACT(MONTH FROM '2024-06-15'); -- 6
SELECT MONTH('2024-06-15');
-- Gün
SELECT EXTRACT(DAY FROM '2024-06-15'); -- 15
SELECT DAY('2024-06-15');
-- Haftanın günü (1=Pazar, 7=Cumartesi — MySQL'de)
SELECT DAYOFWEEK('2024-06-15'); -- 7 (Cumartesi)
-- Günün adı
SELECT DAYNAME('2024-06-15'); -- 'Saturday'
-- Çeyrek
SELECT QUARTER('2024-06-15'); -- 2
-- Haftanın numarası
SELECT WEEK('2024-06-15'); -- 24Gruplama ve raporlamada EXTRACT kullanımı:
-- Aylık sipariş sayısı
SELECT EXTRACT(YEAR FROM order_date) AS yil,
EXTRACT(MONTH FROM order_date) AS ay,
COUNT(*) AS siparis_sayisi,
SUM(total_amount) AS toplam_tutar
FROM orders
GROUP BY EXTRACT(YEAR FROM order_date), EXTRACT(MONTH FROM order_date)
ORDER BY yil, ay;
-- Hangi günler daha çok sipariş geliyor?
SELECT DAYNAME(order_date) AS gun_adi,
COUNT(*) AS siparis_sayisi
FROM orders
GROUP BY DAYNAME(order_date)
ORDER BY siparis_sayisi DESC;DATE_FORMAT — Tarih Formatlama
DATE_FORMAT(tarih, format_stringi)
SELECT DATE_FORMAT(NOW(), '%d/%m/%Y'); -- "15/01/2024"
SELECT DATE_FORMAT(NOW(), '%d %M %Y'); -- "15 January 2024"
SELECT DATE_FORMAT(NOW(), '%H:%i:%s'); -- "14:30:45"
SELECT DATE_FORMAT(NOW(), '%d.%m.%Y %H:%i'); -- "15.01.2024 14:30"Yaygın format kodları:
| Kod | Açıklama | Örnek |
|---|---|---|
%Y | 4 haneli yıl | 2024 |
%y | 2 haneli yıl | 24 |
%m | Ay (01-12) | 01 |
%M | Ay adı (İngilizce) | January |
%d | Gün (01-31) | 15 |
%D | Gün + suffix | 15th |
%H | Saat (24 saat, 00-23) | 14 |
%h | Saat (12 saat, 01-12) | 02 |
%i | Dakika (00-59) | 30 |
%s | Saniye (00-59) | 45 |
%W | Gün adı | Wednesday |
%p | AM/PM | PM |
-- Sipariş raporu formatı
SELECT order_id,
DATE_FORMAT(order_date, '%d.%m.%Y') AS tarih,
DATE_FORMAT(order_date, '%H:%i') AS saat,
total_amount
FROM orders
ORDER BY order_date DESC;📝 PostgreSQL Notu: PostgreSQL'de
DATE_FORMATyerineTO_CHARkullanılır: ``sql SELECT TO_CHAR(order_date, 'DD/MM/YYYY HH24:MI') FROM orders;``
STR_TO_DATE — String'den Tarihe Dönüşüm
-- Farklı formattaki string'i tarihe çevir
SELECT STR_TO_DATE('15/01/2024', '%d/%m/%Y'); -- 2024-01-15
SELECT STR_TO_DATE('Jan 15, 2024', '%b %d, %Y'); -- 2024-01-15
-- Import sırasında tarih dönüşümü
INSERT INTO orders (customer_id, order_date)
VALUES (1, STR_TO_DATE('15.01.2024 14:30', '%d.%m.%Y %H:%i'));Gerçek Dünya Örneği — E-Ticaret Zaman Bazlı Rapor
-- Kapsamlı satış raporu
SELECT
DATE_FORMAT(order_date, '%Y-%m') AS ay,
COUNT(*) AS siparis_sayisi,
COUNT(DISTINCT customer_id) AS benzersiz_musteri,
ROUND(SUM(total_amount), 2) AS toplam_satis,
ROUND(AVG(total_amount), 2) AS ortalama_siparis,
-- Ortalama teslimat süresi
ROUND(AVG(
CASE WHEN status = 'delivered'
THEN DATEDIFF(updated_at, order_date)
END
), 1) AS ort_teslimat_gunu,
-- Bu ayki siparişlerin yüzdesi bekleyen/tamamlanan
ROUND(SUM(CASE WHEN status = 'delivered' THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1)
AS teslim_yuzdesi
FROM orders
WHERE order_date >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
GROUP BY DATE_FORMAT(order_date, '%Y-%m')
ORDER BY ay DESC;Sıkça Yapılan Hatalar
DATETIME sütununda tarih karşılaştırması:
WHERE order_date = '2024-01-15'sadece 00:00:00 olan siparişleri getirir.WHERE DATE(order_date) = '2024-01-15'veyaBETWEEN ... AND ...kullan.DATEDIFF parametre sırası:
DATEDIFF(büyük_tarih, küçük_tarih)pozitif döner. Ters yazarsan negatif döner.MONTH()/YEAR() fonksiyonlarını WHERE'de kullanmak:
WHERE YEAR(order_date) = 2024index kullanamaz.WHERE order_date >= '2024-01-01' AND order_date < '2025-01-01'çok daha hızlı.Timezone farkını görmezden gelmek:
NOW()sunucunun timezone'unu kullanır. Farklı timezone'lardaki kullanıcılar içinCONVERT_TZ()kullan.
Özet
NOW()— tarih+saat,CURDATE()— sadece tarih,CURTIME()— sadece saatDATEDIFF(t1, t2)— gün farkı,TIMESTAMPDIFF(birim, t1, t2)— esnek farkDATE_ADD/DATE_SUB— tarihe ekleme/çıkarma (INTERVALile)EXTRACT(YEAR/MONTH/DAY FROM tarih)— tarih parçası çıkarmaDATE_FORMAT(tarih, format)— tarih formatlamaSTR_TO_DATE(string, format)— string'den tarihe dönüşümWHERE'de tarih fonksiyonu kullanmak index'i bozar — aralık karşılaştırması tercih et
AI Asistan
Sorularını yanıtlamaya hazır