0Pricing
SQL Interview Prep · Ders

Kullanıcı Başına En Uzun Seri

Her grup içindeki en uzun ardışık dizinin hesaplanması.

Kullanıcı Başına En Uzun Seri, CoddyKit'te ücretsiz bir SQL Interview Prep dersidir. Bu, 4 dersinin 2. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, SQL Interview Prep öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. SQL Interview Prep kursu toplamda 4 dersten oluşur.

Soru

Ardışık günleri algılamanın sık sorulan devam sorularından biri şudur: "Her kullanıcı için en uzun ardışık etkin günler serisi nedir?" Ürün ve büyüme ekipleri, etkileşimi ölçmek için bunu sürekli sorar.

Her seriyi nasıl belirleyeceğinizi zaten biliyorsunuz. Yeni adım, kullanıcı başına en uzun seri uzunluğunu bulmak ve çoğu zaman bu en iyi serinin tarihlerini de döndürmektir. Bu ders, doğrudan boşluklar ve adalar iskeleti üzerine kuruludur.

Ada Oluşturucuyu Hatırlama

Önceki derste seri başına gruplama, ada çıpası olarak login_date - ROW_NUMBER() ifadesini kullanıyordu. Her kullanıcının birden fazla adası olabilir; önce ada başına bir satır hesaplayacak, ardından bunu kullanıcı başına bir satıra indireceğiz.

Bu iki katmanlı planı aklınızda tutun: önce adaları oluşturun, sonra adaları toplulaştırın.

WITH numbered AS (
  SELECT user_id, login_date,
    ROW_NUMBER() OVER (
      PARTITION BY user_id ORDER BY login_date
    ) AS rn
  FROM logins
)
SELECT user_id, login_date - rn AS grp
FROM numbered;

Ada Başına Bir Satır

Her adayı, uzunluğunu ve tarih aralığını taşıyan tek bir özet satırında birleştirin. Kullanıcıya ve çıpaya göre gruplayıp metrikleri hesaplayın.

Bu CTE'ye islands adını veriyoruz; böylece sonraki katman bu veriyi temiz bir biçimde okuyabilir.

WITH numbered AS (
  SELECT user_id, login_date,
    ROW_NUMBER() OVER (
      PARTITION BY user_id ORDER BY login_date
    ) AS rn
  FROM logins
),
islands AS (
  SELECT user_id,
    MIN(login_date) AS streak_start,
    MAX(login_date) AS streak_end,
    COUNT(*)        AS streak_len
  FROM numbered
  GROUP BY user_id, login_date - rn
)
SELECT * FROM islands;

Basit Yanıt: MAX Uzunluğu

Mülakatçı yalnızca uzunluğu istiyorsa son adım tek satırlıktır: adaları kullanıcıya göre gruplayıp en yüksek uzunluğu alın.

Başlangıç ve bitiş tarihleri gerekmiyorsa en temiz yanıt budur.

-- ...numbered and islands CTEs as before...
SELECT
  user_id,
  MAX(streak_len) AS longest_streak
FROM islands
GROUP BY user_id
ORDER BY user_id;

Tarihleri de Döndürme

Mülakatçı çoğu zaman şunu da ekler: "Bu serinin ne zaman gerçekleştiğini de gösterin." Sıradan bir MAX, hangi adanın kazandığını size söyleyemez. Adaları her kullanıcı içinde sıralamanız ve 1. sıradakini tutmanız gerekir.

Her kullanıcının en iyi serisi 1. sırayı alsın diye uzunluğa göre azalan biçimde sıralanmış ROW_NUMBER kullanın. Eşitliklerin belirli bir kurala göre çözülmesi için bir eşitlik bozucu ekleyin.

ROW_NUMBER() OVER (
  PARTITION BY user_id
  ORDER BY streak_len DESC, streak_start ASC
) AS rnk

Sıralama ve Filtreleme

Sıralamayı bir CTE içinde sarmalayın, ardından rnk = 1 değerine göre filtreleyin. Bir pencere işlevini doğrudan WHERE içinde filtreleyemezsiniz; bu nedenle ek katman zorunludur.

WITH numbered AS (
  SELECT user_id, login_date,
    ROW_NUMBER() OVER (
      PARTITION BY user_id ORDER BY login_date
    ) AS rn
  FROM logins
),
islands AS (
  SELECT user_id,
    MIN(login_date) AS streak_start,
    MAX(login_date) AS streak_end,
    COUNT(*)        AS streak_len
  FROM numbered
  GROUP BY user_id, login_date - rn
),
ranked AS (
  SELECT *,
    ROW_NUMBER() OVER (
      PARTITION BY user_id
      ORDER BY streak_len DESC, streak_start
    ) AS rnk
  FROM islands
)
SELECT user_id, streak_start, streak_end, streak_len
FROM ranked
WHERE rnk = 1;

Eşitliklerde RANK ve ROW_NUMBER

Bir kullanıcının eşit en yüksek uzunluğa sahip iki serisi varsa ve mülakatçı ikisinin de döndürülmesini istiyorsa ne yapmalısınız? ROW_NUMBER yerine RANK kullanın ve rnk = 1 değerlerini tutun.

  • ROW_NUMBER — kullanıcı başına tam olarak bir kazanan döndürür (eşitliklerde eşitlik bozucu eklemezseniz seçim rastgele olur).
  • RANK — eşit olan en uzun serilerin tümü 1. sırayı paylaşır ve hepsi tutulur.

Hangi davranışı istediklerini netleştirin; bu, uç durumlara dikkat ettiğinizi gösterir.

RANK() OVER (
  PARTITION BY user_id
  ORDER BY streak_len DESC
) AS rnk  -- keep all rnk = 1

Uygulamalı Örnek

7. kullanıcının 1-4 Ocak'ta, ardından 10-11 Ocak'ta ve sonra 20-23 Ocak'ta giriş yaptığını varsayalım. Uzunlukları 4, 2 ve 4 olan üç ada vardır. En uzun uzunluk 4'tür ve eşitlik bulunur.

  • ROW_NUMBER + eşitlik bozucu olarak streak_start kullanıldığında yalnızca 1-4 Ocak serisi döndürülür.
  • RANK kullanıldığında hem 1-4 Ocak hem de 20-23 Ocak serileri döndürülür.

Bunu yüksek sesle ifade etmeniz, yinelenen durumlar üzerine düşündüğünüzü gösterir.

Giriş Yapmayan Kullanıcıları Ele Alma

Bir görüşmeci şöyle sorabilir: "Hiç giriş yapmamış kullanıcılar ne olacak?" Bu kullanıcıların logins tablosunda hiç satırı yoktur; bu nedenle sonuçta görünmezler. Sıfır uzunluklu bir seriyle görünmeleri gerekiyorsa, tam users tablosunu LEFT JOIN ile birleştirin ve COALESCE kullanın.

SELECT u.user_id,
  COALESCE(MAX(i.streak_len), 0) AS longest_streak
FROM users u
LEFT JOIN islands i ON i.user_id = u.user_id
GROUP BY u.user_id;

Performans Notları

Bu kalıp, veriler üzerinde tek bir sıralı geçiş ve ardından bir gruplama yapar. Hızını korumak için:

  • (user_id, login_date) üzerinde bir dizin olduğundan emin olun; böylece pencerenin ORDER BY işlemi sıralama gerektirmez.
  • Kaynakta gün başına birden çok olay varsa yinelenenleri erkenden kaldırın.
  • login_date değerini ORDER BY içinde işlevlere sarmalamaktan kaçının; bu, dizin kullanımını engelleyebilir.

Çok büyük tablolar için bu yaklaşım, kendi kendine birleştirme tabanlı tüm yaklaşımlardan rahatça daha iyi performans gösterir.

Eksiksiz Mülakat Yanıtı

Her kullanıcının tarihleriyle birlikte en uzun serisini döndüren, tamamlanmış ve özenle hazırlanmış sorgu aşağıdadır — beyaz tahtaya yazmanız gereken sürüm budur.

WITH numbered AS (
  SELECT user_id, login_date,
    ROW_NUMBER() OVER (
      PARTITION BY user_id ORDER BY login_date
    ) AS rn
  FROM logins
),
islands AS (
  SELECT user_id,
    MIN(login_date) AS streak_start,
    MAX(login_date) AS streak_end,
    COUNT(*)        AS streak_len
  FROM numbered
  GROUP BY user_id, login_date - rn
),
ranked AS (
  SELECT *,
    ROW_NUMBER() OVER (
      PARTITION BY user_id
      ORDER BY streak_len DESC, streak_start
    ) AS rnk
  FROM islands
)
SELECT user_id, streak_start, streak_end, streak_len
FROM ranked
WHERE rnk = 1
ORDER BY user_id;

Hızlı Kontrol

Gereksinim için doğru aracı seçin.

Özet

Kullanıcı başına en uzun seriyi hesaplamak için:

  • login_date - ROW_NUMBER() çapasıyla adalar oluşturun.
  • Her adayı uzunluğa ve tarih aralığına indirgeyin.
  • Yalnızca uzunluk için kullanıcıya göre gruplayarak MAX(streak_len) kullanın.
  • Tarihleri de almak için adaları kullanıcı başına sıralayın ve 1. sırayı koruyun — eşitlikleri dahil etmek için RANK, tek bir kazanan için ROW_NUMBER kullanın.
  • Sıfır serili kullanıcıları göstermek için users tablosunu LEFT JOIN ile birleştirin.

Sıradaki konu: bir koşulu sağlayan N ardışık satırı tespit etmek.

Sıkça Sorulan Sorular

“Kullanıcı Başına En Uzun Seri” dersi ücretsiz mi?

Evet — “Kullanıcı Başına En Uzun Seri” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve SQL Interview Prep kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. SQL Interview Prep kursu toplamda 4 dersten oluşur.

“Kullanıcı Başına En Uzun Seri” dersinde ne öğreneceğim?

Her grup içindeki en uzun ardışık dizinin hesaplanması. SQL Interview Prep ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

SQL Interview Prep öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te SQL Interview Prep, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 2. dersidir.

“Kullanıcı Başına En Uzun Seri” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu SQL Interview Prep dersinde kod yazıp çalıştırabilir miyim?

Evet. Her SQL Interview Prep dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. Ardışık Takvim Günlerini Tespit Etme
  2. Kullanıcı Başına En Uzun Seri
  3. Koşulu Sağlayan N Ardışık Satır
  4. Bugün İtibarıyla Devam Eden Seri
← SQL Interview Prep Sayfasına Dön