← Kursa Dön
📄 Text · 30 min

Sayısal Fonksiyonlar: ROUND, CEIL, FLOOR, ABS, MOD

Giriş — Sayılarla Oynamak

E-ticaret sitesinde fiyat hesapları yapıyorsun: KDV ekleme, indirim uygulama, kargo ücreti hesaplama, ortalama sipariş tutarı... Bunların hepsi sayısal işlemler. SQL'in yerleşik sayısal fonksiyonları bu hesaplamaları veritabanı seviyesinde yapmanı sağlar — uygulamaya veri çekip orada hesaplamana gerek kalmaz.

🎯 Analoji: Hesap makinesi tuşları gibi düşün. Her fonksiyon farklı bir tuş: yuvarlama, yukarı/aşağı yuvarlama, mutlak değer, mod alma... SQL'in hesap makinesini tanıyalım.


ROUND — Yuvarlama

En sık kullanılan sayısal fonksiyon. Belirtilen ondalık basamağa yuvarlar:

ROUND(sayı, ondalık_basamak)

SELECT ROUND(3.14159, 2);    -- 3.14
SELECT ROUND(3.14159, 0);    -- 3
SELECT ROUND(3.14159);       -- 3 (varsayılan: 0 basamak)
SELECT ROUND(3.5);           -- 4 (yukarı yuvarlar)
SELECT ROUND(3.4);           -- 3 (aşağı yuvarlar)
SELECT ROUND(3.45, 1);       -- 3.5
SELECT ROUND(123.456, -1);   -- 120 (onlar basamağına yuvarla)
SELECT ROUND(123.456, -2);   -- 100 (yüzler basamağına yuvarla)

E-ticaret fiyat hesabı:

-- KDV dahil fiyat (kuruşa yuvarla)
SELECT product_name, 
       price,
       ROUND(price * 1.20, 2) AS price_with_vat
FROM products;

-- İndirimli fiyat
SELECT product_name,
       price,
       ROUND(price * 0.85, 2) AS discounted_price  -- %15 indirim
FROM products WHERE price > 1000;

-- Ortalama sipariş tutarı
SELECT ROUND(AVG(total_amount), 2) AS avg_order FROM orders;

⚠️ Dikkat: MySQL'de banker's rounding (0.5'i çift sayıya yuvarlama) davranışı versiyona göre değişebilir. DECIMAL tipinde ROUND(2.5) = 3 olur (normal yuvarlama). DOUBLE tipinde farklı davranabilir. Para hesaplarında DECIMAL tipi kullan.


CEIL (CEILING) ve FLOOR — Yukarı/Aşağı Yuvarlama

-- CEIL: Her zaman yukarı yuvarla (tavana çık)
SELECT CEIL(3.1);     -- 4
SELECT CEIL(3.9);     -- 4
SELECT CEIL(3.0);     -- 3 (zaten tam sayı)
SELECT CEIL(-3.1);    -- -3 (sıfıra doğru yuvarlar)

-- FLOOR: Her zaman aşağı yuvarla (tabana in)
SELECT FLOOR(3.1);    -- 3
SELECT FLOOR(3.9);    -- 3
SELECT FLOOR(3.0);    -- 3
SELECT FLOOR(-3.1);   -- -4 (negatif yönde aşağı)

Kullanım senaryoları:

-- Kargo ücreti: her 5 kg için 20 TL (yukarı yuvarla)
SELECT product_name,
       weight,
       CEIL(weight / 5) * 20 AS shipping_cost
FROM products WHERE weight IS NOT NULL;
-- 3.2 kg → CEIL(0.64) = 1 → 20 TL
-- 7.8 kg → CEIL(1.56) = 2 → 40 TL
-- 12 kg  → CEIL(2.40) = 3 → 60 TL

-- Sayfa sayısı hesabı
SELECT CEIL(COUNT(*) / 10.0) AS total_pages FROM products;
-- 15 ürün / 10 = 1.5 → CEIL = 2 sayfa

-- İndirimli fiyatı aşağı yuvarla (müşteri lehine)
SELECT product_name,
       price,
       FLOOR(price * 0.90) AS discounted_price
FROM products;
-- 54999.99 * 0.90 = 49499.991 → FLOOR = 49499

ABS — Mutlak Değer

SELECT ABS(-42);    -- 42
SELECT ABS(42);     -- 42
SELECT ABS(0);      -- 0

-- Fiyat farkı (her zaman pozitif)
SELECT p1.product_name,
       p2.product_name,
       ABS(p1.price - p2.price) AS price_difference
FROM products p1, products p2
WHERE p1.product_id = 1 AND p2.product_id = 2;

-- Stok farkı kontrolü
SELECT product_name,
       stock_quantity,
       ABS(stock_quantity - 100) AS deviation_from_target
FROM products;

MOD — Kalan (Modülüs)

SELECT MOD(10, 3);    -- 1 (10 / 3 = 3 kalan 1)
SELECT 10 % 3;        -- 1 (alternatif syntax)
SELECT 10 MOD 3;      -- 1 (alternatif syntax)
SELECT MOD(15, 5);    -- 0 (tam bölünür)

-- Çift/tek ID kontrolü
SELECT product_id, product_name
FROM products
WHERE MOD(product_id, 2) = 0;  -- Çift ID'ler

-- Her 3. satırı seç
SELECT * FROM products WHERE MOD(product_id, 3) = 0;

-- Satır renklerini değiştirme (zebra striping)
SELECT product_id, product_name,
       CASE WHEN MOD(product_id, 2) = 0 THEN 'even' ELSE 'odd' END AS row_type
FROM products;

POWER ve SQRT — Üs ve Karekök

SELECT POWER(2, 10);   -- 1024 (2^10)
SELECT POW(2, 10);     -- 1024 (kısa yazım)
SELECT POWER(10, 3);   -- 1000

SELECT SQRT(144);      -- 12
SELECT SQRT(2);        -- 1.4142135623730951

-- Bileşik faiz hesabı
-- Formül: Anapara * (1 + faiz_oranı) ^ yıl
SELECT 10000 * POWER(1.05, 5) AS future_value;
-- 10000 * 1.05^5 = 12762.82 TL (5 yıl sonraki değer)

Diğer Matematiksel Fonksiyonlar

-- SIGN: İşaret kontrolü (-1, 0, 1)
SELECT SIGN(-42), SIGN(0), SIGN(42);  -- -1, 0, 1

-- TRUNCATE: Ondalık kırpma (yuvarlama yapmaz)
SELECT TRUNCATE(3.789, 2);   -- 3.78 (yuvarlamaz, keser)
SELECT ROUND(3.789, 2);      -- 3.79 (yuvarlar)

-- FORMAT: Binlik ayırıcılı formatlama (string döndürür)
SELECT FORMAT(1234567.89, 2);  -- "1,234,567.89"
SELECT CONCAT('₺', FORMAT(price, 2)) AS formatted FROM products;

-- RAND: Rastgele sayı (0-1 arası)
SELECT RAND();         -- 0.7340291... (her seferinde farklı)
SELECT FLOOR(RAND() * 100) + 1;  -- 1-100 arası rastgele tam sayı

-- LOG, LN: Logaritma
SELECT LOG(100);   -- Doğal logaritma: 4.605...
SELECT LOG10(100); -- 10 tabanında logaritma: 2
SELECT LOG2(256);  -- 2 tabanında logaritma: 8

-- PI
SELECT PI();  -- 3.141593

Gerçek Dünya Örneği — E-Ticaret Fiyat Hesaplama Motoru

-- Kapsamlı fiyat raporu
SELECT 
    product_name,
    price AS liste_fiyati,
    ROUND(price * 1.20, 2) AS kdv_dahil,
    ROUND(price * 0.85, 2) AS indirimli_fiyat,  -- %15 indirim
    ROUND(price * 0.85 * 1.20, 2) AS indirimli_kdv_dahil,
    ROUND(price * 0.15, 2) AS tasarruf,
    -- Taksit hesabı (12 ay, %1.5 faiz/ay)
    ROUND(price * 1.20 * POWER(1.015, 12) / 12, 2) AS aylik_taksit,
    -- Kargo ücreti (her 2 kg için 15 TL)
    CEIL(COALESCE(weight, 1) / 2) * 15 AS kargo_ucreti,
    -- Fiyat kategorisi
    CASE 
        WHEN price < 100 THEN 'Ekonomik'
        WHEN price < 1000 THEN 'Orta'
        WHEN price < 10000 THEN 'Premium'
        ELSE 'Lüks'
    END AS fiyat_kategorisi
FROM products
WHERE is_active = TRUE
ORDER BY price DESC;

Sıkça Yapılan Hatalar

  1. ROUND yerine TRUNCATE kullanmak (veya tam tersi): ROUND(3.75, 1) = 3.8 (yuvarlar), TRUNCATE(3.75, 1) = 3.7 (keser). Hangisini istediğini bil.

  2. FLOAT ile para hesabı: FLOAT yuvarlama hatası yapar. Para hesaplarında DECIMAL tipi ve ROUND fonksiyonu kullan.

  3. Sıfıra bölme: price / 0 hata verir. price / NULLIF(divisor, 0) kullan.

  4. Negatif sayılarla FLOOR/CEIL: FLOOR(-3.5) = -4 (daha negatif), CEIL(-3.5) = -3 (sıfıra yakın). Bu sezgisel olmayabilir.

  5. FORMAT sonucunun string olduğunu unutmak: FORMAT(1000, 2) sonuç "1,000.00" — bu bir string, aritmetik işlem yapılamaz.


Özet

  • ROUND(sayı, basamak) — belirtilen basamağa yuvarlar

  • CEIL / CEILING — her zaman yukarı yuvarlar, FLOOR — her zaman aşağı yuvarlar

  • ABS — mutlak değer (her zaman pozitif)

  • MOD / % — bölme kalanı (çift/tek kontrolü, periyodik işlemler)

  • POWER / POW — üs alma, SQRT — karekök

  • TRUNCATE — yuvarlama yapmadan ondalık kırpma

  • FORMAT — binlik ayırıcılı formatlama (string döndürür)

  • Para hesaplarında DECIMAL + ROUND kullan, FLOAT kullanma

  • Sıfıra bölme koruması: NULLIF(divisor, 0) kullan