Coding Interview Prep · บทเรียน

ช่วงต่อเนื่องที่ยังดำเนินอยู่จนถึงวันนี้

คำนวณช่วงต่อเนื่องที่กำลังดำเนินอยู่ และเริ่มนับใหม่เมื่อเกิดช่วงขาดตอน

บทเรียน 4 จาก 413 ขั้นตอน

ช่วงต่อเนื่องที่ยังดำเนินอยู่จนถึงวันนี้ เป็นบทเรียน Coding Interview Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Coding Interview Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

คำถามเชิงผลิตภัณฑ์

ฟีเจอร์ช่วงต่อเนื่อง เช่น Duolingo หรือ Snapchat ต้องการช่วงต่อเนื่อง ปัจจุบัน ไม่ใช่ช่วงต่อเนื่องที่ยาวที่สุดในอดีต คำถามในการสัมภาษณ์คือ: "สำหรับผู้ใช้แต่ละคน พวกเขาใช้งานต่อเนื่องกันมากี่วันจนถึงวันนี้ หากวันนี้ไม่ได้ใช้งานให้เริ่มนับใหม่เป็น 0"

โจทย์นี้มีรายละเอียดเพิ่มเติมคือ ต้อง ยึดช่วงต่อเนื่องกับวันนี้ (หรือเมื่อวานภายใต้กฎผ่อนผัน) มาสร้างคำตอบโดยอาศัยพื้นฐานเรื่องช่องว่างและกลุ่มช่วงต่อเนื่องที่คุณรู้จักแล้ว

การนิยามการใช้งาน

ขั้นแรก ให้ยืนยันกติกากับผู้สัมภาษณ์ เพราะการตัดสินใจเหล่านี้เปลี่ยนคำสั่งสอบถามได้:

  • ช่วงต่อเนื่องต้องมีกิจกรรม วันนี้ หรือยอมรับ เมื่อวาน ได้ (ช่วงผ่อนผัน)?
  • เหตุการณ์หลายรายการในวันเดียวกันถูกรวมให้เหลือหนึ่งวันหรือไม่?
  • เขตเวลาใดเป็นตัวกำหนดคำว่า "วัน"?

เราจะสมมติว่ามีหนึ่งแถวต่อวันที่มีการใช้งาน และช่วงต่อเนื่องยังเป็นปัจจุบันหากมีวันนี้ OR เมื่อวานรวมอยู่ด้วย

สร้างกลุ่มช่วงต่อเนื่องอีกครั้ง

นำจุดยึดเดิมกลับมาใช้: กำหนดหมายเลขให้วันของผู้ใช้แต่ละคนตามวันที่แล้วลบออก ทุกช่วงที่ต่อเนื่องกันจะมีจุดยึดเดียวกัน ช่วงต่อเนื่องปัจจุบันก็คือกลุ่มที่มี วันสุดท้ายเป็นวันนี้หรือเมื่อวาน

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;

ระบุกลุ่มช่วงต่อเนื่องล่าสุด

กลุ่มช่วงต่อเนื่องล่าสุดของผู้ใช้แต่ละคนคือกลุ่มที่มีค่า streak_end มากที่สุด เราจะตรวจสอบว่าวันสิ้นสุดนั้นใหม่พอที่จะนับว่ายังดำเนินอยู่หรือไม่

CURRENT_DATE ให้ค่าวันนี้ ส่วน CURRENT_DATE - 1 คือเมื่อวาน หาก streak_end เท่ากับค่าใดค่าหนึ่ง ช่วงต่อเนื่องนั้นก็ยังใช้งานอยู่

WITH /* ...numbered, islands... */
latest AS (
  SELECT *,
    ROW_NUMBER() OVER (
      PARTITION BY user_id ORDER BY streak_end DESC
    ) AS rn2
  FROM islands
)
SELECT * FROM latest WHERE rn2 = 1;

ตรวจสอบความเป็นปัจจุบัน

ตอนนี้ให้ตัดสินใจว่ากลุ่มช่วงต่อเนื่องล่าสุดยังใช้งานอยู่หรือไม่ หากวันที่สิ้นสุดเป็นวันนี้หรือเมื่อวาน ช่วงต่อเนื่องปัจจุบันจะมีค่าเท่ากับความยาวของกลุ่มนั้น มิฉะนั้นผู้ใช้ขาดช่วงต่อเนื่องแล้ว และค่าปัจจุบันจะเป็น 0

SELECT user_id,
  CASE
    WHEN streak_end >= CURRENT_DATE - 1
    THEN streak_len
    ELSE 0
  END AS current_streak
FROM latest
WHERE rn2 = 1;

คำสั่งสอบถามช่วงต่อเนื่องปัจจุบันฉบับเต็ม

ประกอบทุกขั้นตอนเข้าด้วยกัน: กำหนดหมายเลข สร้างกลุ่มช่วงต่อเนื่อง เลือกกลุ่มล่าสุดของผู้ใช้แต่ละคน แล้วใช้ CASE ตรวจสอบความเป็นปัจจุบัน นี่คือคำตอบฉบับสมบูรณ์

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,
    MAX(login_date) AS streak_end,
    COUNT(*)        AS streak_len
  FROM numbered
  GROUP BY user_id, login_date - rn
),
latest AS (
  SELECT *,
    ROW_NUMBER() OVER (
      PARTITION BY user_id ORDER BY streak_end DESC
    ) AS rn2
  FROM islands
)
SELECT user_id,
  CASE WHEN streak_end >= CURRENT_DATE - 1
       THEN streak_len ELSE 0 END AS current_streak
FROM latest
WHERE rn2 = 1
ORDER BY user_id;

ความเคร่งครัดแบบเฉพาะวันนี้

หากกฎทางธุรกิจเคร่งครัด — ช่วงต่อเนื่องจะยังใช้งานได้ เฉพาะเมื่อผู้ใช้มีการใช้งานวันนี้ — ให้เปลี่ยนการเปรียบเทียบเป็น streak_end = CURRENT_DATE

เวอร์ชันที่มีช่วงผ่อนผัน (>= CURRENT_DATE - 1) เป็นมิตรกว่าและพบได้บ่อยในแอปจริง เพราะวันนั้นอาจยังไม่สิ้นสุด ควรยืนยันเสมอว่าผู้สัมภาษณ์ต้องการแบบใด

CASE WHEN streak_end = CURRENT_DATE
     THEN streak_len ELSE 0 END AS current_streak

ทางเลือก: ย้อนกลับไปตามลำดับ

กรอบความคิดอีกแบบที่ผู้สัมภาษณ์บางคนชอบคือ คำนวณระยะห่างจากแต่ละวันถึงวันนี้ วันหนึ่งจะเป็นส่วนหนึ่งของช่วงต่อเนื่องปัจจุบันก็ต่อเมื่อมีข้อมูลครบทุกวันตั้งแต่วันนั้นจนถึงวันนี้ หรือกล่าวอีกอย่างคือ เปรียบเทียบ login_date กับ CURRENT_DATE - (offset from the latest)

โดยทั่วไปวิธีกลุ่มช่วงต่อเนื่องจะกระชับกว่า แต่การรู้จักทางเลือกอื่นแสดงให้เห็นถึงความเข้าใจเชิงลึก แนวคิดสำคัญเหมือนกันคือห่วงโซ่ที่ไม่ขาดตอนและยึดกับวันนี้

การรวมผู้ใช้ที่ไม่ได้ใช้งาน

ผู้ใช้ที่ไม่อยู่ใน logins จะไม่มีกลุ่มช่วงต่อเนื่องและหายไป หากต้องรายงานช่วงต่อเนื่องของผู้ใช้ทุกคน (ซึ่งน่าจะเป็น 0) ให้ใช้ LEFT JOIN กับรายชื่อผู้ใช้ แล้วใช้ COALESCE เปลี่ยนผลลัพธ์เป็น 0

SELECT u.user_id,
  COALESCE(s.current_streak, 0) AS current_streak
FROM users u
LEFT JOIN current_streaks s ON s.user_id = u.user_id;

ข้อควรระวังเรื่องเขตเวลา

หากจัดเก็บกิจกรรมเป็นค่าประทับเวลา คำว่า "วันนี้" จะขึ้นอยู่กับเขตเวลา ต้องแปลงเขตเวลาก่อนตัดให้เหลือวันที่

  • จัดเก็บและเปรียบเทียบใน UTC หรือแปลงเป็นเขตเวลาท้องถิ่นของผู้ใช้ก่อน
  • ใช้ event_ts AT TIME ZONE 'UTC' AT TIME ZONE user_tz ใน Postgres แล้วแปลงเป็นวันที่
  • การใช้ ::date โดยไม่พิจารณาเขตเวลากับค่าประทับเวลา UTC อาจทำให้เหตุการณ์ช่วงค่ำไปอยู่ผิดวันตามปฏิทิน

การกล่าวถึงประเด็นนี้ช่วยป้องกันคำถามต่อยอดเกี่ยวกับข้อผิดพลาดคลาสสิกได้

SELECT user_id,
  (event_ts AT TIME ZONE 'UTC'
             AT TIME ZONE 'America/New_York')::date AS local_day
FROM events;

ประสิทธิภาพและสรุปปิดท้าย

สำหรับแดชบอร์ดที่รีเฟรชบ่อย คำสั่งสอบถามนี้จะทำงานต่อผู้ใช้แต่ละคนโดยอ่านข้อมูลเพียงหนึ่งรอบ เพื่อให้ทำงานได้รวดเร็ว:

  • สร้างดัชนีบน (user_id, login_date)
  • อาจจำกัดข้อมูลนำเข้าให้เหลือเฉพาะวันที่ล่าสุด — ช่วงต่อเนื่องปัจจุบันไม่สามารถใช้ข้อมูลที่เก่ากว่าความยาวของช่วงเองได้ ดังนั้นใช้ช่วงข้อมูลย้อนหลัง เช่น 400 วันก็เพียงพอ
  • สร้างข้อมูลรายวันเก็บไว้ในตารางช่วงต่อเนื่อง หากมีการอ่านข้อมูลบ่อยมาก

ตรวจสอบอย่างรวดเร็ว

ยืนยันว่าคุณเข้าใจจุดยึดที่อิงกับ "ปัจจุบัน"

สรุป

การคำนวณช่วงต่อเนื่องที่กำลังใช้งาน ณ วันนี้:

  • สร้างกลุ่มช่วงต่อเนื่องด้วยจุดยึด login_date - ROW_NUMBER()
  • เลือกกลุ่มล่าสุดของผู้ใช้แต่ละคนด้วยค่า streak_end ที่มากที่สุด
  • คืนค่าความยาวของกลุ่มก็ต่อเมื่อ streak_end เป็นวันนี้ (หรือเมื่อวานสำหรับช่วงผ่อนผัน) มิฉะนั้นคืนค่า 0
  • ใช้ LEFT JOIN กับ users เพื่อรวมบัญชีที่ไม่ได้ใช้งาน และจัดการเขตเวลาก่อนตัดให้เหลือวันที่

ตอนนี้คุณมีเครื่องมือครบชุดสำหรับการวิเคราะห์ช่วงต่อเนื่องแล้ว: การตรวจหาช่วงต่อเนื่อง ช่วงต่อเนื่องที่ยาวที่สุด เงื่อนไข N แถวต่อเนื่อง และช่วงต่อเนื่องที่ยังใช้งานอยู่

เริ่มต้นได้ฟรี

เรียนรู้ Coding Interview Prep ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
90
บทเรียน
360

คำถามที่พบบ่อย

บทเรียน “ช่วงต่อเนื่องที่ยังดำเนินอยู่จนถึงวันนี้” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ช่วงต่อเนื่องที่ยังดำเนินอยู่จนถึงวันนี้” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Coding Interview Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ช่วงต่อเนื่องที่ยังดำเนินอยู่จนถึงวันนี้”

คำนวณช่วงต่อเนื่องที่กำลังดำเนินอยู่ และเริ่มนับใหม่เมื่อเกิดช่วงขาดตอน คุณปฏิบัติ Coding Interview Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Coding Interview Prep หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Coding Interview Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “ช่วงต่อเนื่องที่ยังดำเนินอยู่จนถึงวันนี้” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Coding Interview Prep นี้ได้ไหม

ได้ บทเรียน Coding Interview Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. ตรวจจับวันที่ในปฏิทินที่ต่อเนื่องกัน
  2. ช่วงต่อเนื่องที่ยาวที่สุดของผู้ใช้แต่ละคน
  3. แถวต่อเนื่อง N แถวที่ตรงตามเงื่อนไข
  4. ช่วงต่อเนื่องที่ยังดำเนินอยู่จนถึงวันนี้
← กลับไปที่ Coding Interview Prep