Rentetan Terpanjang bagi Setiap Pengguna
Mengira panjang maksimum rentetan berturutan dalam setiap kumpulan.
Rentetan Terpanjang bagi Setiap Pengguna ialah pelajaran Persediaan Temu Duga Pengaturcaraan percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Persediaan Temu Duga Pengaturcaraan, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Persediaan Temu Duga Pengaturcaraan merangkumi sejumlah 4 pelajaran.
Soalan
Susulan yang kerap selepas pengesanan hari berturutan: “Bagi setiap pengguna, apakah rentetan terpanjang hari aktif berturutan mereka?” Pasukan produk dan pertumbuhan sering bertanya soalan ini untuk mengukur penglibatan.
Anda sudah tahu cara mengenal pasti setiap rentetan. Langkah baharu ialah mencari panjang rentetan maksimum bagi setiap pengguna dan, selalunya, turut mengembalikan tarikh rentetan terbaik itu. Pelajaran ini dibina terus berdasarkan rangka asas jurang dan pulau.
Imbas Kembali Pembina Pulau
Daripada pelajaran sebelumnya, pengumpulan bagi setiap rentetan menggunakan login_date - ROW_NUMBER() sebagai sauh pulau. Setiap pengguna boleh mempunyai beberapa pulau; kita akan mengira satu baris bagi setiap pulau terlebih dahulu, kemudian mengurangkannya kepada satu baris bagi setiap pengguna.
Ingat rancangan dua lapis ini: bina pulau dahulu, kemudian agregatkan pulau tersebut.
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;Satu Baris bagi Setiap Pulau
Ringkaskan setiap pulau kepada satu baris ringkasan yang membawa panjang dan julat tarikh. Kumpulkan berdasarkan pengguna dan sauh, kemudian kira ukuran yang diperlukan.
Kami menamakan CTE ini islands supaya lapisan seterusnya boleh membacanya dengan kemas.
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;Jawapan Mudah: Panjang MAX
Jika penemuduga hanya mahu panjang, langkah akhir ialah satu baris: kumpulkan pulau mengikut pengguna dan ambil panjang maksimum.
Inilah jawapan yang paling kemas apabila tarikh mula dan tarikh akhir tidak diperlukan.
-- ...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;Turut Mengembalikan Tarikh
Selalunya penemuduga menambah: “dan tunjukkan bila rentetan itu berlaku.” MAX biasa tidak dapat memberitahu pulau yang menang. Anda perlu menyusun kedudukan pulau dalam setiap pengguna dan mengekalkan kedudukan 1.
Gunakan ROW_NUMBER dengan susunan panjang menurun supaya rentetan terbaik setiap pengguna mendapat kedudukan 1. Tambahkan pemecah seri supaya keputusan bagi seri sentiasa konsisten.
ROW_NUMBER() OVER (
PARTITION BY user_id
ORDER BY streak_len DESC, streak_start ASC
) AS rnkBerikan Kedudukan dan Tapis
Bungkus pemeringkatan dalam CTE, kemudian tapis kepada rnk = 1. Anda tidak boleh menapis fungsi tetingkap secara terus dalam WHERE, jadi lapisan tambahan adalah wajib.
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;RANK berbanding ROW_NUMBER untuk Seri
Bagaimana jika seorang pengguna mempunyai dua rentetan dengan panjang maksimum yang sama dan penemuduga mahu kedua-duanya dikembalikan? Tukar ROW_NUMBER kepada RANK dan kekalkan rnk = 1.
ROW_NUMBER— tepat seorang pemenang bagi setiap pengguna (sewenang-wenangnya apabila seri melainkan pemecah seri ditambah).RANK— semua rentetan terpanjang yang seri berkongsi kedudukan 1 dan semuanya dikekalkan.
Jelaskan tingkah laku yang dikehendaki; ini menunjukkan perhatian anda terhadap kes luar biasa.
RANK() OVER (
PARTITION BY user_id
ORDER BY streak_len DESC
) AS rnk -- keep all rnk = 1Contoh Berpandu
Katakan pengguna 7 log masuk pada 1–4 Januari, kemudian 10–11 Januari, kemudian 20–23 Januari. Terdapat tiga pulau dengan panjang 4, 2 dan 4. Panjang terpanjang ialah 4 dan terdapat seri.
- Dengan
ROW_NUMBER+ pemecah seristreak_start: hanya mengembalikan rentetan 1–4 Januari. - Dengan
RANK: mengembalikan kedua-dua rentetan 1–4 Januari dan 20–23 Januari.
Menyatakan perkara ini dengan lantang menunjukkan bahawa anda telah mempertimbangkan pendua.
Mengendalikan Pengguna Tanpa Log Masuk
Penemuduga mungkin bertanya: "Bagaimana pula dengan pengguna yang tidak pernah log masuk?" Pengguna tersebut tidak mempunyai baris dalam logins, jadi mereka hilang daripada hasil. Jika mereka mesti dipaparkan dengan rentetan sepanjang 0, gunakan LEFT JOIN pada keseluruhan jadual users dan COALESCE.
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;Nota Prestasi
Corak ini melakukan satu laluan bertertib merentasi data, diikuti satu pengelompokan. Untuk mengekalkan kelajuan:
- Pastikan terdapat indeks pada
(user_id, login_date)supaya ORDER BY tetingkap tidak memerlukan pengisihan. - Buang pendua lebih awal jika sumber mempunyai beberapa peristiwa bagi setiap hari.
- Elakkan membungkus
login_datedalam fungsi dalam ORDER BY kerana hal ini boleh menghalang penggunaan indeks.
Bagi jadual yang sangat besar, pendekatan ini dengan mudah mengatasi prestasi mana-mana pendekatan cantuman sendiri.
Jawapan Temu Duga Lengkap
Berikut ialah kueri lengkap dan kemas yang mengembalikan rentetan terpanjang setiap pengguna berserta tarikhnya — versi yang perlu ditulis pada papan putih.
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;Semakan Pantas
Pilih alat yang tepat untuk keperluan tersebut.
Ringkasan
Untuk mengira rentetan terpanjang bagi setiap pengguna:
- Bina kelompok berturutan dengan penambat
login_date - ROW_NUMBER(). - Ringkaskan setiap kelompok kepada panjang serta julat tarikh.
- Untuk panjang sahaja, gunakan
MAX(streak_len)dan kumpulkan mengikut pengguna. - Untuk mendapatkan tarikh juga, tentukan kedudukan kelompok bagi setiap pengguna dan kekalkan kedudukan 1 — gunakan
RANKuntuk memasukkan seri, danROW_NUMBERuntuk satu pemenang sahaja. - Gunakan LEFT JOIN pada users untuk memaparkan pengguna dengan rentetan sifar.
Seterusnya: mengesan N baris berturutan yang memenuhi suatu syarat.
Pelajari Persediaan Temu Duga Pengaturcaraan dengan tutor kecerdasan buatan — percuma
Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.
- Kursus
- 90
- Pelajaran
- 360
Soalan Lazim
Adakah pelajaran “Rentetan Terpanjang bagi Setiap Pengguna” percuma?
Ya — teks penuh “Rentetan Terpanjang bagi Setiap Pengguna” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Persediaan Temu Duga Pengaturcaraan, tingkat taraf kepada CoddyKit PRO. Kursus Persediaan Temu Duga Pengaturcaraan merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “Rentetan Terpanjang bagi Setiap Pengguna”?
Mengira panjang maksimum rentetan berturutan dalam setiap kumpulan. Anda berlatih Persediaan Temu Duga Pengaturcaraan menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.
Adakah saya memerlukan pengalaman untuk memulakan Persediaan Temu Duga Pengaturcaraan?
Tiada pengalaman terdahulu diperlukan. Pembelajaran Persediaan Temu Duga Pengaturcaraan di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.
Berapa lamakah pelajaran “Rentetan Terpanjang bagi Setiap Pengguna” diambil?
Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.
Bolehkah saya menulis dan menjalankan kod dalam pelajaran Persediaan Temu Duga Pengaturcaraan ini?
Ya. Setiap pelajaran Persediaan Temu Duga Pengaturcaraan menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.
Semua pelajaran dalam kursus ini
- Mengesan Hari Kalendar Berturutan
- Rentetan Terpanjang bagi Setiap Pengguna
- N Baris Berturutan yang Memenuhi Syarat
- Rentetan Aktif Semasa Setakat Hari Ini