Tuần 10

Mock Interview, Capstone, và Đường tiếp theo

SQL cho Interview — Tuần cuối

Nhấn phím → để bắt đầu · T để xem mục lục

1. Tổng quan tuần 10

1.1

1.1 Tuần cuối — tích hợp tất cả

Chín tuần qua bạn đã build từng layer kỹ năng. Tuần này không thêm cú pháp mới — mà tích hợp chúng dưới áp lực thời gian thực.

Mục tiêu tuần

Sau tuần 10
Bạn không phải "đã sẵn sàng" — bạn đã có foundation đủ chắc để luyện 4 tuần tiếp với chiến lược rõ ràng. Phỏng vấn SQL không phải về việc nhớ nhiều — mà về reflex và communication. Hai thứ này cần luyện đều, không nhồi nhét.
1.2

1.2 Mock interview vs LeetCode — khác biệt

LeetCode (luyện một mình)Mock interview (có người ra đề)
Áp lực thời gianTùy ý — có thể tạm dừng45 phút cố định, có người nhìn
Đề bàiĐầy đủ schema, sample input/outputĐề thường mơ hồ — phải clarify
Phản hồiSubmit → đúng/saiInterviewer follow-up về trade-off, optimization
Kỹ năng đoCorrectnessCorrectness + clarity + communication + judgment
Sai một bướcSubmit lạiPhải debug live, narrate
Bẫy candidate "LeetCode-only"
Người chỉ luyện LeetCode thường viết code đúng nhưng im lặng trong mock interview — không clarify, không think aloud, không đề cập edge case. Đây là red flag với interviewer dù code đúng.

Tuần này tập trung vào khoảng cách giữa LeetCode và interview thật.

2. Quy trình 45 phút

2.1

2.1 Phase 1 — Read & Clarify (0-5 phút)

Phase 10:00 — 0:05
Đọc đề, hiểu yêu cầu, hỏi clarifying questions. Không gõ phím.

Việc cần làm

  1. Đọc đề 2 lần: lần 1 hiểu, lần 2 chú ý chi tiết.
  2. Restate yêu cầu cho interviewer: "Để confirm, bạn muốn ... đúng không?"
  3. Hỏi về schema: PK, FK, có cột nào NULL không, cardinality (1-1 / 1-N / N-N).
  4. Hỏi về edge case: ties? duplicate? empty input? timezone?
  5. Hỏi về output format: sort thế nào? cột nào? bao nhiêu dòng?

Câu hỏi clarifying chuẩn (template)

Bạn: "Cảm ơn đề. Cho tôi confirm hiểu đúng — yêu cầu là [restate]. Trước khi bắt đầu code, tôi có vài câu hỏi:"

"1. Cột [X] có thể NULL không?"

"2. Bảng có khả năng có dòng trùng không?"

"3. Khi có ties (vd cùng salary), output mong đợi thế nào?"

"4. Output cần sort theo cột nào?"

Phase này có vẻ tốn thời gian, nhưng 5 phút clarifying tiết kiệm 20 phút debug. Skip phase này là sai lầm phổ biến nhất.

2.2

2.2 Phase 2 — Plan & Stub (5-15 phút)

Phase 20:05 — 0:15
Identify pattern, viết khung CTE, narrate plan. Vẫn ít gõ phím — chủ yếu nói.

Việc cần làm

  1. Identify pattern (tuần 8 cheatsheet): "Tôi nghĩ đây là pattern X vì có tín hiệu Y."
  2. Phân rã thành các bước CTE — nói ra trước khi viết.
  3. Viết khung CTE rỗng với comment — interviewer thấy structure.
  4. Confirm hướng đi với interviewer: "Cách tiếp cận này hợp lý chứ?"

Script chuẩn

Bạn: "Đây có vẻ là pattern top-N per group. Tôi sẽ chia thành 3 bước:

1. Filter các đơn paid trong 2024 — CTE paid_2024.

2. Aggregate tổng / customer + rank trong country — CTE ranked.

3. Filter top 3 + tính % country — output cuối.

Tôi viết khung trước, sau đó điền chi tiết từng CTE. Hợp lý chứ?"

WITH
    paid_2024 AS (
        -- TODO: orders status='paid' và 2024
    ),
    ranked AS (
        -- TODO: SUM theo customer + ROW_NUMBER theo country
    )
SELECT
    -- TODO: top 3 mỗi country với pct
;

Khung trống với TODO comments — interviewer thấy bạn structure trước, code sau.

2.3

2.3 Phase 3 — Code & Iterate (15-35 phút)

Phase 30:15 — 0:35
Điền chi tiết từng CTE. Narrate khi gõ. Test mental sau mỗi CTE.

Cách tiếp cận từng CTE

  1. Đặt đầu vào và đầu ra rõ ràng trong đầu — CTE này nhận gì, trả gì?
  2. Viết SELECT trước, FROM/WHERE sau — quyết định cột output trước.
  3. Test mental với sample data — chạy CTE qua 3-5 dòng giả lập trong đầu.
  4. Bug? Đừng panic. Comment câu chính, viết SELECT * FROM cte_name LIMIT 5 để inspect output.

Narrate khi gõ — script ngắn

Bạn: "Tôi đang viết CTE thứ nhất. Filter status='paid' và order_date trong 2024 — nửa-mở để tránh fence-post error..."

Bạn: "OK CTE 1 xong. Test mental: 5 đơn input → 3 đơn paid 2024. Đúng. Sang CTE 2..."

Tránh — silent coding
Khi gõ 5 phút không nói gì, interviewer mất context. Ít nhất 30 giây / minute nên có narration. Quy tắc: "Tôi đang làm gì → tại sao → kết quả mong đợi".
Tránh — over-talking
Ngược lại — narrate quá nhiều cũng tệ. Khi gõ logic phức tạp, OK im lặng 30 giây. Sau đó tóm tắt: "Vừa xong logic X."
2.4

2.4 Phase 4 — Test, Edge, Optimize (35-45 phút)

Phase 40:35 — 0:45
Test với sample data, đề cập edge cases, thảo luận optimization và alternative approaches.

Việc cần làm

  1. Test trace — chạy query qua sample input, narrate kết quả từng CTE.
  2. Đề cập edge cases proactively — không đợi hỏi:
    • "Nếu cột X NULL — query xử lý thế nào?"
    • "Nếu có ties trong ranking — pattern xử lý ra sao?"
    • "Nếu bảng rỗng — output là gì?"
  3. Đề xuất optimization:
    • Index nào hữu ích?
    • Có alternative approach (window function vs subquery vs JOIN)?
    • Trade-off correctness vs readability vs performance?
  4. Sẵn sàng follow-up: "Nếu yêu cầu mở rộng thành ..., bạn sẽ thay đổi gì?"

Script chuẩn cho Phase 4

Bạn: "Tôi đã hoàn thành. Để tôi đi qua edge cases nhanh:

1. Cột customer_id ở orders không có NULL theo schema, nên LEFT JOIN không tạo NULL phantom.

2. ROW_NUMBER cần tie-breaker — tôi đã thêm order_id DESC.

3. Bảng rỗng → CTE rỗng → output rỗng. OK.

Về performance: query benefit từ composite index (country, signup_date). Trên dữ liệu 100M dòng, có thể cần thêm partial index trên status='paid'."

Phase này phân biệt candidate junior với senior. Junior viết xong rồi dừng. Senior viết xong rồi chủ động đi qua edge cases và optimization.

3. Communication và Think Aloud

3.1

3.1 Tại sao think aloud quan trọng

Trong interview SQL, đáp số đúng là điều kiện cần, không phải đủ. Interviewer đánh giá:

  1. Process — bạn tiếp cận problem thế nào?
  2. Communication — có giải thích được cho team không?
  3. Judgment — biết khi nào nên dùng kỹ thuật A vs B?
  4. Self-awareness — nhận ra khi đang sai và tự sửa?

Tất cả những thứ này chỉ visible qua narration. Code im lặng = interviewer không thấy gì cả. Hai candidate ra cùng đáp án nhưng một người narrate tốt thì sẽ pass, người kia có thể fail.

Quan trọng — đây là kỹ năng phải LUYỆN
Think aloud không tự nhiên với hầu hết người. Cần luyện chủ đích: Sinh viên Việt thường ngại nói English/Vietnamese while coding — đây là rào cản phải vượt. Bắt đầu với chính ngôn ngữ mạnh nhất của bạn.
3.2

3.2 Script tham khảo cho 4 phase

Phase 1 — Clarify

"Cảm ơn đề bài. Cho tôi confirm hiểu đúng — yêu cầu là [restate].
Trước khi code, tôi có 3 câu hỏi:
1. Cột X có thể NULL không?
2. Có khả năng có dòng trùng trong bảng Y không?
3. Khi có ties, output mong đợi như thế nào?"

Phase 2 — Plan

"Đây có vẻ là pattern [X] vì có tín hiệu [Y].
Tôi sẽ chia thành N bước:
- Bước 1: ...
- Bước 2: ...
- Bước 3: ...
Tôi viết khung CTE trước, rồi điền chi tiết. Cách tiếp cận này hợp lý chứ?"

Phase 3 — Code (mỗi 1-2 phút)

"Tôi đang viết CTE [tên]. Mục đích: [input → output].
Logic chính: [tóm tắt 1 câu]."

[Sau khi xong CTE]
"OK, CTE [tên] xong. Test mental: với input mẫu [...], kết quả là [...]. Sang CTE tiếp."

Phase 4 — Wrap up

"Tôi đã hoàn thành. Để đi qua edge cases:
- NULL: [xử lý thế nào]
- Ties: [xử lý thế nào]
- Empty: [output gì]

Về performance: query benefit từ index [...]. Trên dữ liệu lớn,
alternative approach là [...] với trade-off [...]."
3.3

3.3 Common mistakes — và cách tránh

MistakeCách tránh
Silent coding — gõ 5+ phút không nóiSet timer trong đầu; mỗi 1 phút có 1 câu narration
Mumbling / unclearNói câu hoàn chỉnh, không "ừm... à... thì..."
Over-talking — narrate mỗi keystrokeNarrate ở level "intent + result", không phải mỗi dòng
Defensive khi sai"Tôi nghĩ tôi vừa sai bước này. Để tôi sửa..." — interviewer thích self-correction
Không hỏi clarifyingLuôn ít nhất 2-3 câu hỏi Phase 1
Skip edge casesPhase 4 dành riêng cho việc này — không bỏ qua
Argumentative khi bị challengeNghe → "Bạn đúng, tôi đã không nghĩ tới ..." → fix. Senior là người admit nhanh
Bỏ cuộc khi stuck"Tôi đang stuck ở chỗ này. Cách tiếp cận tôi đã thử là [A]. Tôi đang nghĩ thử [B]." — interviewer có thể hint
Insight cuối
Interviewer là đồng nghiệp tương lai. Họ không cố để bạn fail — họ đánh giá xem làm việc cùng bạn có dễ không. Mọi behavior trong 45 phút là proxy cho behavior 5 năm sau.

4. Edge Case Checklist

4.1

4.1 NULL checklist — 7 câu hỏi

Trước khi submit, đi qua 7 câu hỏi NULL này như reflex:

  1. Cột nào có thể NULL? Đọc schema. Cột FK thường nullable.
  2. WHERE có toán tử <>, !=, NOT IN? NULL có thể bị loại bỏ unintentionally.
  3. JOIN trên cột nullable? Dòng có NULL key bị loại — có cần LEFT JOIN không?
  4. COUNT()? COUNT(*) đếm cả NULL, COUNT(col) bỏ. Đúng chưa?
  5. SUM/AVG? Bỏ NULL khi tính. AVG có chia trên ít hơn số dòng — đúng yêu cầu?
  6. Concat / function? CONCAT trong MySQL trả NULL nếu một đối số NULL.
  7. ORDER BY? NULL ở đầu hay cuối tùy phương ngữ và ASC/DESC. Có cần NULLS FIRST/LAST?
Mock script Phase 4
"Đi qua NULL handling: cột manager_id của Employees có thể NULL (CEO). Trong INNER JOIN của tôi, CEO bị loại — đó là intent. Nếu yêu cầu giữ CEO, dùng LEFT JOIN. Cột salary NOT NULL theo schema nên SUM/AVG OK."
4.2

4.2 Ties, Empty, và Duplicate checklist

Ties — khi hai dòng "bằng nhau"

  1. ROW_NUMBER với ORDER BY có thể tied → cần tie-breaker để deterministic.
  2. RANK vs DENSE_RANK — chọn đúng theo yêu cầu (đã học tuần 6).
  3. Median với số lượng chẵn — lấy AVG hai dòng giữa hay chỉ lấy một?
  4. "Top 3" — có thể trả >3 dòng nếu ties (RANK), hay đúng 3 (ROW_NUMBER)?

Empty — bảng rỗng hoặc kết quả rỗng

  1. Aggregate trên tập rỗng: SUM trả NULL (không phải 0). COUNT(*) trả 0.
  2. Subquery scalar trả 0 dòng → toàn bộ outer query có thể NULL.
  3. Yêu cầu "Top 1" trên bảng rỗng → 0 dòng output, không phải "không có gì".

Duplicate — dòng trùng

  1. Bảng có PK chưa? Nếu không, có thể có dòng trùng — DISTINCT cần thiết?
  2. JOIN nhân dòng (1 → N) — sau JOIN còn unique không?
  3. UNION vs UNION ALL — bạn có cần loại trùng?
Bẫy DISTINCT che bug JOIN
Nếu thấy mình thêm DISTINCT vì "dòng trùng quá nhiều", thường là JOIN sai cardinality. DISTINCT che bug, không sửa bug. Quay lại check JOIN trước.
4.3

4.3 Date/Timezone và Boundary checklist

Date arithmetic

  1. Cột là DATE hay TIMESTAMP? TIMESTAMP có giờ-phút-giây — BETWEEN có thể fence-post error.
  2. Nửa-mở cho range: d >= '2024-01-01' AND d < '2025-01-01' luôn đúng cho cả DATE và TIMESTAMP.
  3. "Last 30 days" — bao gồm hôm nay không? Confirm với interviewer.
  4. "This year" — fiscal year hay calendar year?

Timezone

  1. Cột TIMESTAMP có timezone không? TIMESTAMP vs TIMESTAMPTZ.
  2. Group theo "ngày" — ngày theo timezone server hay user?
  3. So với 'YYYY-MM-DD' literal — nó ở timezone gì?

Câu hỏi Phase 1 chuẩn

Bạn: "Cột order_date kiểu DATE hay TIMESTAMP? Nếu TIMESTAMP, có timezone không? Yêu cầu 'tháng 3' theo timezone nào?"

Hỏi câu này là tín hiệu candidate có production experience. Junior thường giả định cột là DATE thuần.

5. Capstone Walkthrough

5.1

5.1 Đề bài — Cohort Retention Analysis

Schema

users ( user_id INT PRIMARY KEY, signup_date DATE NOT NULL, country VARCHAR(50) ) events ( event_id INT PRIMARY KEY, user_id INT NOT NULL, -- FK to users event_type VARCHAR(20), -- 'login', 'purchase', 'click' event_time TIMESTAMP NOT NULL )

Yêu cầu

Cho mỗi cohort theo tháng (theo signup_date trong năm 2024), tính:

Sắp xếp theo cohort_month. Round retention 2 chữ số.

Mock interview vibe

Bài này khó vừa phải — Medium-Hard. Tích hợp date arithmetic, LEFT JOIN, conditional aggregation, CTE multi-step. Một interviewer có kinh nghiệm sẽ hỏi follow-up về: ties, NULL, performance, mở rộng thành weekly cohort.

5.2

5.2 Phase 1 — Clarify (mock dialogue)

Bạn: "Cảm ơn đề. Cho tôi confirm hiểu đúng: với mỗi cohort tháng signup trong 2024, tính cohort_size và 2 retention rate (Day-7 và Day-28). Đúng chứ?"

Interviewer: "Đúng."

Bạn: "Tôi có 4 câu hỏi:

1. Cột events.user_id luôn match một user trong users chứ? Hay có thể có orphan?"

Interviewer: "Luôn match — referential integrity được enforce."

Bạn: "2. 'Event trong 7 ngày từ signup' — bao gồm ngày signup không? Tức [signup, signup+7) hay (signup, signup+7]?"

Interviewer: "Bao gồm signup. Tức (signup_date, signup_date + 7 days]."

Bạn: "3. event_time là TIMESTAMP. Khi tính 'within 7 days', so với ngày hay datetime?"

Interviewer: "Tính theo datetime. signup_date được coi là 00:00 ngày đó."

Bạn: "4. User signup ngày 2024-12-30 thì rất ít có data Day-28 trong dataset. Vẫn phải xuất hiện chứ? Retention sẽ thấp hoặc 0%?"

Interviewer: "Hỏi tốt. Giả sử dataset đủ — bao gồm events đến hết 2025-01-31. Cohort 12/2024 vẫn tính được Day-28."

4 câu hỏi này lộ ra: orphan handling, half-open interval, datetime semantics, data completeness. Đây là tín hiệu strong.

5.3

5.3 Phase 2 — Plan

Bạn: "Đây là pattern cohort retention đã rèn. Tôi sẽ chia thành 4 CTE:

1. cohort_users — user signup 2024 với cohort_month = đầu tháng signup.

2. user_retention — JOIN với events, đánh flag has_w1 và has_w4 cho mỗi user.

3. cohort_metrics — aggregate theo cohort_month: COUNT users + AVG flags.

4. Output cuối — round + format.

Tôi viết khung trước. Hợp lý chứ?"

WITH
    cohort_users AS (
        -- TODO: users 2024 + cohort_month (first day of month)
    ),
    user_retention AS (
        -- TODO: cho mỗi user, flag w1 và w4
        --       LEFT JOIN events, dùng EXISTS-style aggregation
    ),
    cohort_metrics AS (
        -- TODO: GROUP BY cohort_month
        --       COUNT(*) cohort_size, AVG(flag_w1), AVG(flag_w4)
    )
SELECT
    cohort_month,
    cohort_size,
    ROUND(100.0 * w1_rate, 2) AS week_1_retention,
    ROUND(100.0 * w4_rate, 2) AS week_4_retention
FROM cohort_metrics
ORDER BY cohort_month;
5.4

5.4 Phase 3 — Code

WITH
    cohort_users AS (
        SELECT
            user_id,
            signup_date,
            DATE_FORMAT(signup_date, '%Y-%m-01') AS cohort_month
            -- PostgreSQL: DATE_TRUNC('month', signup_date)
        FROM users
        WHERE signup_date >= '2024-01-01'
          AND signup_date <  '2025-01-01'
    ),
    user_retention AS (
        SELECT
            cu.user_id,
            cu.cohort_month,
            -- Flag = 1 nếu có ít nhất 1 event trong window
            MAX(CASE
                WHEN e.event_time >  cu.signup_date
                 AND e.event_time <= cu.signup_date + INTERVAL 7 DAY
                THEN 1 ELSE 0
            END) AS has_w1,
            MAX(CASE
                WHEN e.event_time >  cu.signup_date
                 AND e.event_time <= cu.signup_date + INTERVAL 28 DAY
                THEN 1 ELSE 0
            END) AS has_w4
        FROM cohort_users cu
        LEFT JOIN events e ON e.user_id = cu.user_id
        GROUP BY cu.user_id, cu.cohort_month
    ),
    cohort_metrics AS (
        SELECT
            cohort_month,
            COUNT(*)                           AS cohort_size,
            AVG(has_w1)                        AS w1_rate,
            AVG(has_w4)                        AS w4_rate
        FROM user_retention
        GROUP BY cohort_month
    )
SELECT
    cohort_month,
    cohort_size,
    ROUND(100.0 * w1_rate, 2) AS week_1_retention,
    ROUND(100.0 * w4_rate, 2) AS week_4_retention
FROM cohort_metrics
ORDER BY cohort_month;

~30 dòng cho bài Medium-Hard. CTE đặt tên rõ — đọc top-down dễ. Mỗi bước test riêng được.

5.5

5.5 Phase 4 — Edge Cases và Optimization

Bạn: "Đi qua edge cases:

1. User signup không có event: LEFT JOIN cho NULL events. MAX(CASE...) trả 0 — đúng (retention = 0%).

2. NULL event_time: schema NOT NULL nên không xảy ra.

3. Multiple events per user: MAX(CASE...) đảm bảo 0/1 flag, không over-count.

4. Cohort tháng 12: vẫn tính Day-28 vì interviewer confirm dataset đủ.

5. Empty input: query trả 0 dòng — đúng behavior.

Về performance:

- Index quan trọng: events(user_id, event_time) cho LEFT JOIN.

- users(signup_date) cho WHERE filter.

- Trên dữ liệu lớn (100M events), CTE user_retention có thể nặng vì group theo user_id. Alternative: dùng EXISTS thay vì MAX(CASE) — early exit nhanh hơn:"

-- Alternative cho user_retention với EXISTS
SELECT
    cu.user_id, cu.cohort_month,
    EXISTS (SELECT 1 FROM events e WHERE e.user_id = cu.user_id
            AND e.event_time > cu.signup_date
            AND e.event_time <= cu.signup_date + INTERVAL 7 DAY) AS has_w1,
    -- tương tự cho has_w4
FROM cohort_users cu;

Bạn: "Mở rộng có thể có: Day-N retention với N là parameter, weekly cohort thay vì monthly, group thêm theo country. Cấu trúc CTE giúp adapt dễ — chỉ thay CTE đầu hoặc thêm cột country vào group keys."

6. Practice Scenarios

6.1

6.1 5 capstone scenarios cho self-practice

Mỗi scenario dưới đây là độ khó Medium-Hard. Tự làm 45 phút mỗi cái với timer, ghi âm narration, đánh giá lại.

  1. Top spenders với percentile

    Cho orders(customer_id, total, order_date). Tìm customer ở top 10% spending mỗi tháng (theo tổng amount), kèm rank trong top 10%, tổng tháng đó của họ, và % của họ trên top 10% group.

    Pattern: Percentile + Top-N within group + Cumulative metric.

  2. Session reconstruction

    Cho events(user_id, event_time). Định nghĩa session: events của cùng user cách nhau ≤ 30 phút thuộc cùng session. Tính cho mỗi user: số session, độ dài session trung bình, session dài nhất.

    Pattern: Gaps and Islands theo time + window function.

  3. Funnel analysis

    Cho events(user_id, event_type, event_time) với event_type ∈ {'view', 'add_to_cart', 'checkout', 'purchase'}. Tính tỷ lệ conversion mỗi bước (view→cart, cart→checkout, checkout→purchase) trong 7 ngày qua. Mỗi user phải làm bước trước trong vòng 24h trước khi bước sau được tính.

    Pattern: Self-join + date arithmetic + conditional aggregation.

  4. Hierarchical reporting

    Cho employees(id, name, manager_id, salary). Tính cho mỗi manager: số subordinate (trực tiếp + gián tiếp), tổng salary tất cả subordinate, salary trung bình. Thêm cột "depth" = độ sâu cây dưới manager đó.

    Pattern: Recursive CTE + aggregation.

  5. Daily active users với MAU/WAU

    Cho logins(user_id, login_date). Cho mỗi ngày trong 30 ngày qua, tính: DAU (số user unique login hôm đó), WAU rolling (số user unique login trong 7 ngày qua), DAU/WAU ratio (stickiness).

    Pattern: Cumulative + window with frame + cohort-style aggregation.

6.2

6.2 Cách tự đánh giá mock interview

Sau mỗi scenario tự làm, đánh giá theo 4 chiều (mỗi chiều 1-5 điểm):

ChiềuCâu hỏi tự đánh giá
CorrectnessCode chạy đúng? Edge cases được xử lý? Mental test pass?
Code qualityCTE đặt tên rõ? Code đọc top-down dễ? Tránh anti-pattern?
CommunicationNarrate liên tục? Phase 1 clarifying đầy đủ? Phase 4 đề cập optimization?
Time managementPhân chia thời gian hợp lý 4 phase? Kết thúc trong 45 phút?

Self-improvement loop

  1. Làm scenario, ghi âm.
  2. Tự chấm 4 chiều.
  3. Note điểm yếu nhất (vd "Communication 2/5 — quá im lặng phase 3").
  4. Scenario tiếp tập trung sửa chỉ một chiều.
  5. Lặp.
Insight
Sinh viên thường focus 100% vào correctness và bỏ ba chiều còn lại. Trong interview thật, 4 chiều tổng hợp quyết định pass/fail. Một bài 80% đúng + communication mạnh thường thắng 95% đúng + im lặng.

7. Lịch luyện 4 tuần trước phỏng vấn

7.1

7.1 Lịch 4 tuần — week-by-week

TuầnFocusDaily routine
T-4 (foundation refresh)Easy/Medium volume — refresh kỹ năng, build speed10 LeetCode/ngày, mix Easy 70% + Medium 30%. Time mỗi bài. Note pattern.
T-3 (pattern depth)Medium/Hard targeted — luyện 7 pattern (tuần 8 cheatsheet)5 problems/ngày, 1 pattern/ngày. Mỗi bài viết 2-3 dòng note pattern.
T-2 (mock practice)3 mock interview/tuần với peer hoặc tự làm (45 min, ghi âm)3 mock + 5 LeetCode/ngày để maintain. Sau mỗi mock, self-eval 4 chiều.
T-1 (taper + review)Giảm volume, tăng review. Đọc lại slide tuần 8 (patterns) và tuần 9 (performance).2 mock cuối tuần. 3 LeetCode/ngày. Đọc lại note patterns. Nghỉ ngơi 1 ngày trước phỏng vấn.
Tránh — common mistakes
7.2

7.2 Resources — đầu tư đáng giá

Practice platforms

Books worth reading

Mock interview partners

Communities

8. Behavioral và Hỏi-Đáp

8.1

8.1 Câu hỏi behavioral và follow-up phổ biến

Trước technical phần

Sau technical phần

Bạn nên hỏi (cuối phỏng vấn)

Câu hỏi cho thấy bạn quan tâm production reality, không phải chỉ technical skill.

9. Tổng kết

9.1

9.1 Bạn đã đi qua những gì

TuầnChủ đềKỹ năng signature
1Mô hình quan hệĐại số quan hệ, SELECT cơ bản
2Lọc nâng cao và NULL3VL, CASE WHEN, string/date functions
3AggregationGROUP BY, HAVING, conditional aggregation
4JOIN sâuINNER/OUTER/SELF/CROSS, anti-join
5Subquery và Set OpsCorrelated, EXISTS, UNION/INTERSECT/EXCEPT
6Window FunctionsROW_NUMBER/RANK, LAG/LEAD, frame clause
7CTE và RecursiveWITH, multi-step decomposition, hierarchy traversal
8Pattern Interview7 patterns + recognition reflex
9Performance & Phương ngữEXPLAIN, index, anti-patterns, dialect awareness
10Mock & Capstone4-phase process, communication, edge case checklist

Bạn đã build từng layer — từ cú pháp cơ bản đến refactor query Hard, từ pattern recognition đến performance optimization, từ code im lặng đến think-aloud có cấu trúc.

Điều quan trọng nhất bạn mang theo
Không phải cú pháp — bạn có thể tra docs. Không phải pattern names — chúng có cheatsheet.

Đó là tư duy tập hợp (set thinking), phản xạ pattern recognition, và communication có cấu trúc. Ba thứ này không tra docs được, không thuộc lòng được — phải luyện. Bạn đã có nền — giờ là 4 tuần luyện trước phỏng vấn thật.

Chúc may mắn!

Pattern recognition is muscle memory.
Communication is rehearsable.
Edge cases are checklists.

Mỗi cái đều luyện được. Phỏng vấn SQL không phải trắc nghiệm IQ — nó là kỹ năng có thể build.

Bạn đã build trong 10 tuần. Giờ là lúc áp dụng.


SQL cho Interview — Lộ trình 10 tuần · Hết

Mục lục

Nhấn T hoặc Escape để đóng