MySQL'in kendine has yazımları
SELECT `name`, IFNULL(stock, 0) AS stok,
IF(price > 1000, 'Pahalı', 'Normal') AS sinif
FROM products
ORDER BY price DESC
LIMIT 5, 5; -- 5 satır atla, 5 satır getir
`ters tırnak`ile tanımlayıcılar.LIMIT atla, getirkısa yazımı (dikkat: sıra tersine benzer).IF(koşul, a, b)veIFNULL.
Tarih ve metin
SELECT DATE_FORMAT(order_date, '%Y-%m') AS ay,
COUNT(*) AS siparis,
GROUP_CONCAT(DISTINCT channel ORDER BY channel SEPARATOR ' / ') AS kanallar
FROM orders
WHERE YEAR(order_date) = 2024
GROUP BY DATE_FORMAT(order_date, '%Y-%m')
ORDER BY ay;
Tuzaklar
||mantıksal VEYA'dır: Metin birleştirmek içinCONCATkullan. (Bu uygulamada MySQL modunda||yazarsan uyarılırsın.)- Varsayılan karşılaştırma büyük/küçük harf ve aksan duyarsızdır (
utf8mb4_0900_ai_ci):'Şahin' = 'sahin'doğru olabilir. - Eski sürümlerde GROUP BY gevşekliği:
ONLY_FULL_GROUP_BYkapalıysa gruplanmamış sütunlar rastgele değer döner. - FULL OUTER JOIN yoktur; LEFT + RIGHT + UNION ile yazılır.
- Tam sayı bölmesi yoktur:
7 / 2 = 3.5000; tam sayı için7 DIV 2.
Derinleş: MySQL'de veri temizliği ve upsert
MySQL'in kendine özgü fonksiyonları, özellikle ham veriyi temizlerken ve yükleme yaparken işe yarar. Üç tanesi çok sık kullanılır: STR_TO_DATE, TIMESTAMPDIFF ve INSERT ... ON DUPLICATE KEY UPDATE.
STR_TO_DATE: metinden tarihe
raw_signups tablosunda tarihler iki biçimde geliyor. STR_TO_DATE(metin, biçim) metni gerçek DATE tipine çevirir; biçim uymazsa NULL döndürür (katı SQL modunda uyarı/hata). DATE_FORMAT ise tersini yapar.
SELECT id, signup_date,
CASE WHEN signup_date LIKE '__.__.____'
THEN STR_TO_DATE(signup_date, '%d.%m.%Y')
ELSE STR_TO_DATE(signup_date, '%Y-%m-%d') END AS kayit_tarihi
FROM raw_signups
ORDER BY id
LIMIT 6;
TIMESTAMPDIFF: süre hesabı
TIMESTAMPDIFF(birim, başlangıç, bitiş) iki zaman arasındaki farkı istenen birimde tam sayı (aşağı yuvarlanmış) olarak verir. DATEDIFF(a, b) ise yalnızca gün farkıdır ve argüman sırası terstir (bitiş önce).
SELECT r.city,
COUNT(*) AS teslim,
ROUND(AVG(TIMESTAMPDIFF(MINUTE, o.placed_at, o.delivered_at)), 1) AS ort_dk
FROM lk_orders o
JOIN lk_restaurants r ON r.restaurant_id = o.restaurant_id
WHERE o.status = 'teslim'
GROUP BY r.city
ORDER BY ort_dk DESC;
Upsert: ON DUPLICATE KEY UPDATE
Birincil veya benzersiz anahtar çakışırsa satırı güncelleyen bu yazım, MySQL'de idempotent yüklemenin en kısa yoludur:
CREATE TABLE gunluk_sayac (gun DATE PRIMARY KEY, siparis INT NOT NULL); INSERT INTO gunluk_sayac (gun, siparis) SELECT DATE(placed_at), COUNT(*) FROM lk_orders WHERE placed_at >= '2024-12-30' AND placed_at < '2024-12-31' GROUP BY DATE(placed_at) ON DUPLICATE KEY UPDATE siparis = VALUES(siparis); SELECT * FROM gunluk_sayac;
Aynı ifadeyi ikinci kez çalıştırmak satır eklemez, değeri günceller. MySQL 8.0.20+ VALUES() yerine takma adlı yazımı önerir: INSERT ... AS yeni ON DUPLICATE KEY UPDATE siparis = yeni.siparis.
Sık hata: Dönüşümden sonra NULL sayısını kontrol etmemek. Biçime uymayan bir metin (ör. 31/12/2024) STR_TO_DATE ile NULL'a döner ve kayıt sessizce “tarihsiz” kalır. Temizlik sorgusunun hemen ardından SUM(CASE WHEN yeni_tarih IS NULL THEN 1 ELSE 0 END) ile kaç kaydın dönüşemediğini say. Benzer şekilde TIMESTAMPDIFF aşağı yuvarladığı için 59 saniyelik bir fark 0 dakika görünür; hassas ortalamalarda SECOND biriminde hesaplayıp 60'a böl.
| Yazım | Davranış | Dikkat |
|---|---|---|
ON DUPLICATE KEY UPDATE | Çakışmada günceller | Birden çok benzersiz anahtar varsa hangisinin çakıştığı belirsizleşir |
REPLACE INTO | Çakışan satırı siler, yenisini ekler | Silme, yabancı anahtar CASCADE'lerini ve trigger'ları tetikler |
INSERT IGNORE | Çakışan satırı atlar | Başka hataları da sessizce yutar |