Soru
Görüşmeci“Tabloda tekrarlanan e-posta adreslerini bul ve her birinden yalnızca en eski kaydı tutacak şekilde temizle.” Takip: “Müşteriler ilk siparişten ikinci siparişe ortalama kaç günde dönüyor?”
Önce netleştir
Kod yazmadan önce sorulacak sorular. Her biri farklı bir sorguya götürür; sormamak en sık puan kaybıdır.
- “Aynı e-posta” büyük/küçük harf ve boşluk farkını yok sayıyor mu?
- “En eski” kayıt tarihine mi, kimliğe mi göre?
- Silme mi istiyorsunuz, yoksa tekilleştirilmiş bir görünüm mü?
- Tek siparişi olan müşteriler ortalamaya nasıl girer? (girmez)
Yaklaşım
- Anahtarı normalize et: LOWER(TRIM(email)).
- GROUP BY + HAVING COUNT(*) > 1 ile tekrarları bul.
- ROW_NUMBER() OVER (PARTITION BY anahtar ORDER BY kimlik) ile her grupta 1 numaralıyı tut.
- İkinci sipariş için aynı ROW_NUMBER kalıbı: rn = 1 ve rn = 2'yi yan yana getir.
Çözüm 1: tekrarları bulmak ve sıralamak
WITH s AS (
SELECT id, LOWER(TRIM(email)) AS anahtar,
ROW_NUMBER() OVER (PARTITION BY LOWER(TRIM(email)) ORDER BY id) AS rn,
COUNT(*) OVER (PARTITION BY LOWER(TRIM(email))) AS adet
FROM raw_signups
WHERE email IS NOT NULL
)
SELECT anahtar, adet, id AS tutulacak_id
FROM s
WHERE rn = 1 AND adet > 1
ORDER BY adet DESC, anahtar;
Çözüm 2: ikinci sipariş: koşullu toplama
WITH s AS (
SELECT customer_id, order_date,
ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date, order_id) AS rn
FROM orders
),
p AS (
SELECT customer_id,
MAX(CASE WHEN rn = 1 THEN order_date END) AS ilk,
MAX(CASE WHEN rn = 2 THEN order_date END) AS ikinci
FROM s
GROUP BY customer_id
)
SELECT COUNT(ikinci) AS donen, ROUND(AVG(julianday(ikinci) - julianday(ilk)), 1) AS ort_gun
FROM p;
Aynı ROW_NUMBER kalıbı iki farklı soruyu çözer: tekrar temizlemede “1 numara kalır”, sıralı olaylarda “1 ve 2 numarayı yan yana koy”. MAX(CASE WHEN rn = 2 ...) uzun formattan geniş formata çevirmenin taşınabilir yoludur; LEAD ile de yazılabilir.
Sınır durumları
| Durum | Ne olur? |
|---|---|
| NULL e-posta | PARTITION BY NULL değerleri tek grup sayar; WHERE email IS NOT NULL ile ayır |
| Aynı gün iki sipariş | ORDER BY order_date tek başına belirsiz; order_id ekle |
| Tek siparişli müşteri | ikinci NULL olur; AVG NULL'u atlar, COUNT(ikinci) dönenleri sayar |
| Tam tekrar satırlar | Kimlik de aynıysa rowid ya da tüm sütunlarla GROUP BY gerekir |
Takip soruları
- DELETE ile nasıl silersin? (WHERE id NOT IN (SELECT MIN(id) ... GROUP BY anahtar))
- Silmeden önce ne yaparsın? (aynı WHERE ile SELECT, yedek, işlem)
- Medyan dönüş süresi ortalamadan neden daha anlamlı olabilir?
Görüşmeci neye bakıyor?Anahtarı normalize etmeyi düşünmen, silmeden önce görüntülemeyi önermen ve eşitlikte belirleyici bir sıralama eklemen.