Ana içeriğe geç
Kesit SQL
Orta · Veri Mühendisliği

Veri kalitesi testleri

Benzersizlik, NULL, referans bütünlüğü ve aralık kontrolleri.

Uygulamada aç, 5 alıştırmayı çözÜcretsiz, hesap gerekmez, kurulum yok.

Bu sayfa dersin okuma sürümüdür. Metin bir kutuyu çalıştırmanı ya da adıma geçmeni söylüyorsa dersi uygulamada aç.

Testler “sıfır satır” döndürmeli

dbt ve benzeri araçlardaki yaygın yaklaşım: Her test, sorunlu satırları döndüren bir sorgudur. Sonuç boşsa test geçer.

-- 1) Benzersizlik: order_id tekrar ediyor mu?
SELECT order_id, COUNT(*) FROM orders GROUP BY order_id HAVING COUNT(*) > 1;
-- 2) Referans bütünlüğü: var olmayan ürüne ait sipariş satırı var mı?
SELECT oi.* FROM order_items oi
LEFT JOIN products p ON p.product_id = oi.product_id
WHERE p.product_id IS NULL;
-- 3) Kabul edilen değerler
SELECT DISTINCT status FROM orders
WHERE status NOT IN ('delivered', 'shipped', 'cancelled', 'returned');
-- 4) Aralık / mantık kontrolleri
SELECT * FROM order_items WHERE quantity <= 0 OR discount < 0 OR discount >= 1;
SELECT * FROM products WHERE cost > price;

Tek sorguda kalite özeti

SELECT 'customers.email NULL' AS test, COUNT(*) AS hatali FROM customers WHERE email IS NULL
UNION ALL SELECT 'customers.city NULL', COUNT(*) FROM customers WHERE city IS NULL
UNION ALL SELECT 'orders sipariş tarihi < kayıt tarihi', COUNT(*)
  FROM orders o JOIN customers c ON c.customer_id = o.customer_id WHERE o.order_date < c.signup_date;

Derinleş: veri kalitesinin beş boyutu

“Veri kötü” demek eyleme dönüşmez. Kaliteyi ölçülebilir boyutlara ayırınca her sorun için bir test, bir sahip ve bir eşik tanımlanabilir:

BoyutSoruÖrnek test
TamlıkOlması gereken değer var mı?Müşterinin ilçesi boş mu?
TekillikHer varlık bir kez mi?Aynı order_id iki kez geçiyor mu?
GeçerlilikDeğer izin verilen aralıkta / biçimde mi?Puan 1–5 dışında mı?
Tutarlılıkİlişkili kayıtlar birbiriyle çelişiyor mu?Sipariş, müşterinin kayıt tarihinden önce mi?
GüncellikVeri beklenen tazelikte mi?Son kayıt kaç gün önce geldi?

Bunlara bazen doğruluk (değer gerçeği yansıtıyor mu) da eklenir; ama doğruluk genelde dış bir kaynakla karşılaştırma gerektirir ve tek başına SQL ile ölçülemez.

Lezzet Kurye kalite karnesi

SELECT 'tamlık' AS boyut, 'lk_customers.district boş' AS test, COUNT(*) AS hatali
FROM lk_customers WHERE district IS NULL
UNION ALL
SELECT 'tekillik', 'lk_orders.order_id tekrarı', COUNT(*)
FROM (SELECT order_id FROM lk_orders GROUP BY order_id HAVING COUNT(*) > 1) t
UNION ALL
SELECT 'geçerlilik', 'puan 1-5 dışında', COUNT(*)
FROM lk_ratings WHERE food_score NOT BETWEEN 1 AND 5 OR courier_score NOT BETWEEN 1 AND 5
UNION ALL
SELECT 'tutarlılık', 'sipariş, müşteri kaydından önce', COUNT(*)
FROM lk_orders o JOIN lk_customers c ON c.customer_id = o.customer_id
WHERE substr(o.placed_at, 1, 10) < c.signup_date
UNION ALL
SELECT 'tutarlılık', 'davetli, davet edenden önce kayıtlı', COUNT(*)
FROM lk_customers c JOIN lk_customers d ON d.customer_id = c.referred_by
WHERE c.signup_date < d.signup_date
UNION ALL
SELECT 'güncellik', 'son siparişten bu yana gün (rapor günü 2025-01-03)',
       julianday('2025-01-03') - julianday(MAX(date(placed_at)))
FROM lk_orders;

Karnede iki gerçek bulgu var: 1.209 müşterinin 74'ünde ilçe boş (tamlık %93,9) ve davetli 294 müşterinin 136'sı onu davet edenden önce kaydolmuş görünüyor. İkincisi tipik bir tutarlılık sorunudur: ya kayıt tarihi sonradan güncelleniyor ya da davet bilgisi başka bir akıştan geliyor. Kaynağı bilen ekiple konuşmadan “düzeltme”. Sipariş ile kayıt tarihi testi ise 0 döner: temiz çıkan test de bilgidir, her yükte yine çalışmalıdır.

Eşik ve önem derecesiHer testin bir eşiği olsun: tekillik ihlali sıfır tolerans (hattı durdur), tamlıkta %95 altı uyarı gibi. dbt'de severity: warn / error ve warn_if, error_if ayarları bunu sağlar.

Sık hata: testleri yalnızca yeni tabloya yazmak. En değerli testler, kaynaklar arasındaki ilişkileri (sipariş–müşteri, değerlendirme–sipariş) kontrol eden tutarlılık testleridir; çünkü tek tabloya bakan testler bu çelişkileri hiç görmez.

Alıştırmalara geç (5)