cswork / libraryOpen practice workspace

Interview guides · Blue Health Intelligence

Blue Health Intelligence Data Scientist Interview Questions & Guide 2026

Timed data scientist practice for Blue Health Intelligence: short SQL and probability sets run end to end, then scored against a rubric.

The 60-second brief

As a Data Scientist at Blue Health Intelligence, you operate at the intersection of complex healthcare data and actionable clinical insights. You are responsible for transforming vast, fragmented health datasets into models that drive decision-making for some of the most critical players in the healthcare ecosystem. Your work directly impacts how health plans, providers, and employers understand population health, cost drivers, and quality of care.

Coding rounds for this role are usually data-manipulation shaped rather than data-structure shaped: group-bys, joins, time windows, ranking within a partition. Confirm the format before spending a week on graph traversal.

Focus areas

  • Risk-adjust outcomes before comparing providers or panels
  • Build member-month denominators from overlapping coverage spans
  • Reconstruct drug exposure intervals from dispensing records

Overview

This role requires a high degree of technical rigor combined with the ability to translate abstract findings into strategic business value. You will collaborate closely with cross-functional teams to build, validate, and deploy machine learning solutions that scale. Because Blue Health Intelligence handles sensitive and high-stakes information, you must demonstrate not only technical proficiency but also a disciplined, ethical approach to data science in a regulated environment.

The Blue Health Intelligence interview process

Blue Health Intelligence candidates report 3 rounds · ≈ 3-5 weeks. The stages below are what candidates describe, not a published process.

Recruiter Screening

Most candidates lose this call inside the first two minutes, during the walkthrough of their own background. The account runs chronologically, sits at the level of tools and titles, and never arrives at a decision anyone could have disagreed with. Anchor on a problem instead of a timeline: what the team could not answer, what you did about it, what happened next. Ninety seconds is enough, and stopping on time leaves room for the half of the call that belongs to you. What you ask about how work gets prioritised signals your level more reliably than the walkthrough does.

What to demonstrate

  • Whether your background summary has a shape (problem, decision, consequence) or is a chronological list of tools and employers
  • Whether you can account for gaps, short stints and the reason you are looking, unprompted and without hedging
  • The substance of the questions you ask back, which an experienced screener reads as a level signal

How to prepare

  • Time your opening walkthrough against a clock. If it runs past two minutes, compress the earliest role into a single clause and spend the recovered time on the most recent one
  • Write one honest sentence for every gap or short stint visible on your resume and offer it before being asked about it
  • Prepare questions about how work arrives and gets prioritised: who writes the request, how often priorities change, and what happens to an analysis after it is delivered

Technical Deep-Dives

A handful of shapes account for most of what gets asked in this format: a ranking or deduplication inside groups, a running or rolling total, a period-over-period comparison, and a cohort tracked forward over time. Recognising the shape quickly is most of the speed here; deriving it from scratch while a clock runs is where the time goes. Know that a window function keeps every row while a GROUP BY collapses them, and know which one the question needs. If the exercise is in Python instead of SQL, the same shapes arrive as groupby with transform, shift and merge, and the same grain mistakes are available.

What to demonstrate

  • Whether you reach the right construct without a detour, such as ROW_NUMBER over a partition to deduplicate instead of a self-join against a MAX subquery
  • Whether you know what your window frame actually is, since adding ORDER BY inside OVER changes the default frame and silently changes a running total
  • Whether the thing runs. A near-miss that throws an error scores below a plainer query that returns the right rows.

How to prepare

  • Write each of the four shapes once from memory against a small schema and keep the working version somewhere you will reread it: dedupe with ROW_NUMBER, a running total, a month-over-month change with LAG, and a retention table
  • Compute one running total twice on data with tied timestamps, once on the default frame and once with ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, and look at where the two disagree
  • If Python is on the table, rebuild the dedupe and the running total with groupby and cumsum, then assert the two implementations return identical rows

Team-Based Interviews

An extra round usually exists because something is still open after the standard loop: a skill the earlier interviews did not sample, a level decision, or two interviewers who disagreed. It is rarely a rerun of what you already did well. Ask the recruiter who you are meeting, what function they sit in, and how long the session runs. That is an ordinary scheduling question, and the answer changes what you should prepare. What separates a strong candidate here is treating the round as a fresh evaluation with its own bar, rather than assuming earlier performance carries you through or sinks you.

What to demonstrate

  • Whether you can answer well on ground the earlier rounds did not cover, without leaning on what you already said to someone else
  • Consistency of the facts in your stories: the same sample size, timeframe, team size and scope of your own role as in earlier conversations
  • How you handle an unfamiliar format live, including whether you ask what kind of answer is wanted before producing one

How to prepare

  • Ask the recruiter for the interviewer's function, the length, and whether to expect a coding surface, a discussion, or a presentation. Preparing for a 30 minute conversation with a partner team is not the same work as preparing for a 60 minute technical block.
  • Write out what each earlier round actually covered, then list the two or three areas nobody probed. That gap is the most likely subject of the extra round.
  • Re-read the numbers in the project stories you have already told, so a second telling does not quietly contradict the first.

Where candidates lose points

Treating clinical measurements as missing at random

A lab result, a vital sign, or a screening exists because someone ordered it, and ordering tracks suspicion of disease, visit frequency, and site workflow. Imputing the mean or dropping incomplete rows biases the population estimate and can flip the sign of an association, because the untested are systematically healthier or systematically disengaged. The presence indicator is often more predictive than the value, which is a warning sign rather than a feature win: a model that learns test ordering will not transfer to a site with different protocols.

Pre-post evaluation on a high-cost or high-risk cohort

Cohorts selected on an extreme value of the outcome regress toward the mean on their own. Members identified as the top 1 percent of spend in one year spend far less the next, whether or not anyone intervenes, because the selecting year captured both chronic severity and one-off events. A pre-post design on such a cohort will report savings every time. A concurrent comparison group selected by the same rule in the same period, or a regression discontinuity at the selection threshold, is the minimum credible design.

Reporting a p-value with no effect size or interval

Give the estimated difference with a confidence interval in the units the business cares about, then say whether that whole interval is worth acting on. A p-value only addresses whether you can rule out exactly zero; it says nothing about magnitude.

Ending an analysis without a recommendation or next step

Close with what you would do and what would change your mind, stated as a condition you can check later. If the evidence is genuinely inconclusive, recommend the specific next measurement and say what it costs in time or exposure.

Questions & practice

Explain the trade-offs between different machine learning models for a classification problem.

Medium · machine learning and modelling

Approach

  1. Frame the prediction: the label, the moment of prediction, and the action it triggers.
  2. Check what information would not exist at prediction time, and exclude it.
  3. Set a baseline first, so any model has something honest to beat.

Follow-up

  • How would you choose the decision threshold, and who owns that choice?
  • Where could label leakage enter this setup?

Four data-quality rules over corrected and cancelled lab results

Easy · data quality · record supersession · unit drift

lab_result has result_id, order_id, patient_id, loinc_code, value_numeric, value_text, units, reference_low, reference_high, specimen_collected_ts, resulted_ts, result_status (preliminary, final, corrected, cancelled), supersedes_result_id. Return one row per rule with a failing count, a failing share, and one example result_id, for these rules: more than one surviving row per (order_id, loinc_code) after resolving corrections and dropping cancelled; resulted_ts earlier than specimen_collected_ts; a numeric result whose unit is not the modal unit for its loinc_code; value_numeric and value_text both null on a row with result_status 'final'.

Approach

  1. Resolve the correction chain before anything else. Drop result_status 'cancelled', then within each (order_id, loinc_code) keep the row whose result_id appears in no other row's supersedes_result_id. That terminal node is the surviving value and the rule holds even if a correction is loaded with a backdated timestamp.
  2. Build each rule as a boolean mask over a named frame rather than as a filtered copy, so the failing share has an explicit, per-rule denominator. Rule three is eligible only on rows with a non-null value_numeric; rule four only on final rows.
  3. For the unit rule, derive the modal unit per loinc_code from the data instead of hardcoding an expected unit. The failure being hunted is one analyte reported in two units whose values differ by a fixed factor, which no range check catches because both sets of numbers look plausible.
  4. Emit a tidy frame with columns rule, eligible_rows, failing_rows, failing_share, example_result_id. A printed report cannot be diffed between runs; a frame can be stored and alerted on.
  5. Order the output by failing_share descending so the run has a lead finding rather than four equal-weight lines.

Worked solution (25 min)

  1. Drop cancelled rows, then compute the set of result_ids referenced by supersedes_result_id and keep rows not in that set.
  2. Rule one: group the survivors by (order_id, loinc_code) and count rows above 1.
  3. Rule two: mask on resulted_ts < specimen_collected_ts over rows where both timestamps are present.
  4. Rule three: compute the mode of units per loinc_code over rows with non-null value_numeric, then mask rows whose unit differs from it.
  5. Rule four: mask rows with result_status 'final' and both value columns null. Assemble the four results into one frame with counts, shares and an example id.

Expected result: A four-row frame. After the resolver, rule one should report zero failing groups on a well-formed extract; a non-zero count there means the supersession chain branches or a duplicate load occurred, and that is the finding to lead with rather than a percentage.

Verify it yourself

  • Running the resolver a second time on its own output is a no-op, and exactly one row survives per (order_id, loinc_code).
  • No result_id appearing in any supersedes_result_id survives the resolver.
  • Seed one row with a converted unit for an analyte otherwise reported in a single unit and confirm rule three catches exactly that row and nothing else.
  • Each rule's failing_share uses its own eligible_rows, so a rule with no eligible rows returns share 0 rather than a division error.

Follow-up

  • The modal-unit rule fires on 8 percent of one analyte. How do you decide whether that is a unit-conversion bug or a second legitimate assay?
  • What would you add to catch a value that is inside its reference range but physiologically impossible?
  • Which of these four rules should block a downstream pipeline and which should only alert, and why?

Expand overlapping coverage spans into fractional member-months

Medium · interval expansion · denominators · vectorisation

member_enrollment has span_id, member_id, plan_id, product_type, effective_date, termination_date (NULL while active). Both dates are inclusive. Write a function returning one row per calendar month of a stated year with total member-months, where a member contributes covered days in the month divided by days in that month, capped at one month per member even when two spans overlap after a plan change or a retroactive span. Do not expand to one row per member-day: the sample has 400,000 members. Output: month, member_months.

Approach

  1. Resolve NULL termination_date to the reporting end date and say so in a comment. An open span is not an infinite span, and clipping it at the year end is what keeps the denominator finite and auditable.
  2. Merge overlapping and adjacent spans per member before touching months. Sort by member_id and effective_date, carry a running maximum of the end date, and open a new merged group when effective_date exceeds that running max plus one day. Adjacent means a gap of zero days, which a plan change produces constantly.
  3. Cross join the merged spans to the 12 month boundaries rather than to days. Overlap days = (min(span_end, month_end) - max(span_start, month_start)).days + 1, clipped below at 0. That is at most 12 rows per span instead of 365.
  4. Divide overlap days by the number of days in that month, so February and July are weighted correctly, then sum by month.
  5. Validate on a constructed member before trusting the aggregate: a single span covering the whole year must sum to exactly 12.0.

Follow-up

  • Product type changes mid-year. The metric must be reported by product_type. Where does the cap now apply and what breaks?
  • An eligibility file arrives with a retroactive termination that shortens a span you already reported on. How do you restate?
  • Why member-months rather than distinct members, in one sentence, for a director who wants the simpler number?

Can you walk through a Python script you wrote to automate a data cleaning process?

Medium · sql and data manipulation

Approach

  1. Check whether any join is one-to-many before aggregating, or the sums inflate.
  2. State the window function and its partition and ordering out loud before writing it.
  3. Say which table is the grain you start from, and join outward from it.

Follow-up

  • What breaks if events arrive late or out of order?
  • How does the query change if the join becomes one-to-many?

How do you approach complex SQL queries when dealing with large, nested datasets?

Medium · sql and data manipulation

Approach

  1. Say which table is the grain you start from, and join outward from it.
  2. Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
  3. Check whether any join is one-to-many before aggregating, or the sums inflate.

Follow-up

  • How would you verify this result without re-running the same query?
  • How does the query change if the join becomes one-to-many?

How do you ensure your code is reproducible and maintainable for the rest of the team?

Medium · sql and data manipulation

Approach

  1. Check whether any join is one-to-many before aggregating, or the sums inflate.
  2. Say which table is the grain you start from, and join outward from it.
  3. Compute rates by summing numerator and denominator separately, never by averaging rates.

Follow-up

  • How does the query change if the join becomes one-to-many?
  • How would you verify this result without re-running the same query?

Count thirty-day unplanned readmissions without counting transfers

Medium · self-join · event streams · exclusions

encounter holds encounter_id, patient_id, facility_id, encounter_type, admit_ts, discharge_ts, admission_type, discharge_disposition, is_planned_admission and index_encounter_id. For inpatient stays discharged between 2025-01-01 and 2025-11-30, return the 30-day unplanned readmission rate overall and by facility_id. Exclude an index stay when is_planned_admission is TRUE or discharge_disposition is transfer_acute, expired, hospice or ama. A qualifying readmission is any unplanned inpatient admission for the same patient with admit_ts after the index discharge_ts and within 30 days of it. One stay can be both a readmission and the next index stay.

Approach

  1. Decide between LEAD and EXISTS explicitly and say why. LEAD over the patient's admission stream gives the literal next stay, so an intervening planned admission hides a later unplanned one. The measure asks whether any unplanned admission fell in the window, which is an EXISTS or a self-join with a range predicate.
  2. Exclude transfers at the index end before anything else. An acute-to-acute transfer closes one encounter and opens another at a different facility_id within hours, so without the transfer_acute exclusion the facilities that move the sickest patients out look the worst.
  3. Apply the index exclusions as a set, including stays with NULL discharge_ts, which are still open and have no measurable window.
  4. Stop the denominator early enough that every index stay had a full 30 days of observation plus encounter lag. That is why the window ends 2025-11-30 rather than at year end.
  5. Compute the rate at stay level, not patient level, then compare the raw facility rates against an observed-over-expected framing before anyone publishes a ranking.

Worked solution (30 min)

  1. CTE ip: inpatient encounters with a non-null discharge_ts.
  2. CTE index_stays: ip rows with discharge_ts in the window, is_planned_admission FALSE, and discharge_disposition not in the four excluded values.
  3. Flag each index stay with EXISTS against ip for the same patient_id where is_planned_admission is FALSE, encounter_id differs, admit_ts > index.discharge_ts and admit_ts <= index.discharge_ts + 30 days.
  4. Aggregate numerator and denominator overall and grouped by facility_id.
  5. Re-run with the transfer exclusion removed and record how much the rate moves.

Expected result: Eligible index stays, stays with a qualifying readmission, and the quotient, overall and per facility_id. Removing the transfer exclusion returns a higher rate, and the gap between the two is a number you should be able to quote.

Verify it yourself

  • Numerator never exceeds denominator, and an index stay with two qualifying readmissions still contributes exactly one.
  • No index stay in the output has discharge_disposition transfer_acute, expired, hospice or ama.
  • A 0-day window gives a rate of exactly 0, and a 365-day window gives a rate no lower than the 30-day one.
  • Facility rates weighted by facility denominators reconcile to the overall rate.

Follow-up

  • A patient has three stays ten days apart. How many index stays and how many readmissions, and why does the answer depend on the stated rule?
  • Which comparison would you publish across facilities, raw rate or observed over expected, and what does risk adjustment still fail to fix?
  • index_encounter_id already exists on the table. Would you trust it, and how would you audit it against your own logic?

What metrics do you prioritize when evaluating a model’s success?

Medium · product sense and metrics

Approach

  1. State what result would change your recommendation, so the answer is falsifiable.
  2. Decompose the metric into the rates that drive it, and say which one you would check first.
  3. Restate the decision this analysis has to support, and who acts on the answer.

Follow-up

  • Which segment would you cut first, and what would that rule out?
  • What would you do if the primary metric and the guardrail moved in opposite directions?

Size a clinic-randomised trial when the intracluster correlation binds

Medium · cluster randomisation · design effect · stepped wedge

A care-coordination change is delivered at the clinic level and cannot be withheld from some members of a participating clinic. Forty-eight clinics are available for 1:1 randomisation. The primary outcome is the 90-day primary care contact rate among newly enrolled members, baseline 0.62, with a target of plus 5 percentage points. Each clinic contributes about 60 eligible members a year, and the intracluster correlation on this outcome is 0.02. Two-sided alpha 0.05, 80 percent power. Give clinics required per arm, say whether 48 suffices, and what you would do.

Approach

  1. Compute the individually randomised sample size first, then inflate it by the design effect 1 + (m - 1) x ICC, where m is the average cluster size. The design effect is the price of correlation within clinics and is the single largest term in this calculation.
  2. Convert the inflated individual N into clusters by dividing by m, and compare with the 24 clinics available per arm.
  3. Check the ceiling before proposing a longer accrual window. As m grows, effective members per cluster approaches 1 / ICC, here 50, so 24 clinics can never contribute more than 1,200 effective members per arm no matter how many members each one enrols. If the required effective N exceeds that, no amount of accrual rescues the parallel design.
  4. Propose the designs that actually change the arithmetic: a stepped wedge in which every clinic crosses over so each contributes a within-cluster comparison, or a smaller randomisation unit (provider pod) if the intervention can be delivered at that level without contamination.
  5. Add the two refinements a reviewer will ask for: use a t-distribution with roughly 2k - 2 degrees of freedom rather than z when k is small (here about 46 df, which raises N by about 4 percent), and use covariate-constrained randomisation on baseline contact rate so 48 clinics do not land badly imbalanced by chance.

Worked solution (30 min)

  1. Individual n per arm = 7.849 x (0.62 x 0.38 + 0.67 x 0.33) / 0.05^2 = 7.849 x 0.4567 / 0.0025 = 1,434.
  2. Design effect = 1 + (60 - 1) x 0.02 = 2.18.
  3. Inflated n per arm = 1,434 x 2.18 = 3,126 members, so clusters per arm = 3,126 / 60 = 52.1, round up to 53.
  4. Compare with 24 clinics available per arm: the study is short by more than a factor of two.
  5. Compute the ceiling: 1 / 0.02 = 50 effective members per clinic, so 24 clinics give at most 1,200 effective members per arm against the 1,434 required.

Expected result: 53 clinics per arm (106 total) against 48 available. The effective-sample ceiling of 1,200 per arm is below the 1,434 needed, so the parallel cluster design is infeasible at any panel size; the answer is a stepped wedge, a smaller randomisation unit, or a pre-registered larger MDE.

Verify it yourself

  • Verify the design effect directly: 1 + 59 x 0.02 = 2.18.
  • Verify the diminishing return: doubling m from 60 to 120 raises effective members per cluster only from 27.5 to 35.5, not from 60 to 120.
  • Recompute with t-based quantiles at 46 df and confirm the requirement moves by a few percent, not by a factor.

Follow-up

  • Sketch the stepped-wedge analysis model. What does a secular trend do to the estimate if you leave period effects out?
  • The ICC was estimated from a prior year at 0.02 with a wide interval. How do you size under ICC uncertainty?
  • Six clinics withdraw after randomisation. What does that do to power compared with losing the same number of members?

Readmission rate rose while every facility improved

Medium · simpsons paradox · mix shift · risk adjustment

Quarter over quarter the 30-day unplanned readmission rate for an attributed population rose from 14.2 to 15.1 percent, yet all eleven facilities in encounter show a flat or falling rate over the same period. You have encounter (facility_id, admit_ts, discharge_ts, encounter_type, admission_type, discharge_disposition, drg_code, is_planned_admission, index_encounter_id) and twelve months of prior medical_claim_line for comorbidities. Explain the direction reversal numerically, and state what the population-level number should be reported as instead.

Approach

  1. Confirm the reversal is arithmetic, not a definition difference, by recomputing both the facility rates and the pooled rate from the same query with the same index-stay exclusions.
  2. Decompose the pooled change exactly with a Kitagawa split. With facility weights w and within-facility rates r, the change equals the sum over facilities of (w_1 - w_0) times (r_0 + r_1)/2, the mix term, plus the sum of (w_0 + w_1)/2 times (r_1 - r_0), the within term. If the mix term exceeds the total change and the within term is negative, the reversal is volume shifting toward facilities with higher baseline rates.
  3. Ask why the weights moved. Check index-stay volume by facility, and check whether an exclusion changed behaviour: acute-to-acute transfers (discharge_disposition 'transfer_acute') must not open an index stay, and if one facility began transferring more, its denominator shrinks toward its sickest retained patients.
  4. Check case mix inside the facilities too, using drg_code and comorbidities drawn from the 12 months of claims before admit_ts, excluding complications of the index stay itself. A facility rate can be flat while its case mix worsens.
  5. Replace the raw pooled rate with an observed over expected ratio, where expected is the sum of predicted probabilities from a model fitted on age, sex and prior comorbidities. Raw rates are not comparable across a population whose facility and case mix is moving.

Follow-up

  • Your O/E ratio is 1.04 with a 95 percent interval of 0.96 to 1.13. What does that let you say to a facility, and what does it not?
  • If one facility contributes 40 percent of index stays, how does that change how you present the decomposition?
  • How would you handle a member with two index stays in the quarter, where the second is also a readmission from the first?

Suggested practice checklist

For someone who has spent the last year in notebooks, dashboards or modelling work and has not written raw SQL under time pressure. The first four days rebuild query fluency against a fixture you control and can verify by hand; the last three attach that fluency to the rest of the loop.

Day 1 — Build a fixture you can check answers against

  • Create a local Postgres or SQLite database with four tables (users, sessions, events, orders) holding roughly 200 rows you generated yourself, so you know the contents well enough to predict every result.
  • Deliberately seed the cases that break queries: a user with no sessions, a session with no events, two orders sharing a timestamp, a NULL in one join key, and one duplicated user row.
  • Before writing any SQL, hand-compute five answers on paper (how many users placed at least one order, median orders per ordering user, and three others) and save them as the ground truth for the week.

Deliverable: A one-command seed script plus a text file of five hand-computed answers to grade every later query against.

Day 2 — Joins, filters and NULL semantics

  • Answer "which users have no orders" three ways (LEFT JOIN with IS NULL, NOT EXISTS, NOT IN) and confirm that the NOT IN version returns zero rows once the subquery contains a NULL, because the comparison is never TRUE.
  • Reproduce the LEFT JOIN that silently collapses to an inner join by putting a right-table predicate in WHERE, then fix it by moving the predicate into the ON clause, and record both row counts.
  • Create a fan-out bug on purpose by joining orders to order_items and summing the order total, then correct it with a pre-aggregated subquery and explain in one line which table changed the grain.

Deliverable: One annotated .sql file holding the three join traps, each with the wrong result and the corrected result side by side.

Day 3 — Window functions and frames

  • Write three window queries against the fixture: a running order total per user, the rank of each order within its user by value, and the day gap to that user's previous order, then check each against the day-one ground truth.
  • Run ROW_NUMBER, RANK and DENSE_RANK over a column containing ties, print all three side by side, and write one sentence on when each is the correct choice.
  • Switch one query from the default frame (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, which is what you get when ORDER BY is present and no frame is written) to ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, and explain why the output differs only when the ORDER BY column has duplicates.

Deliverable: Three verified window queries plus a short note explaining the RANGE versus ROWS difference in your own words.

Day 4 — The four analytical query patterns

  • Write a monthly retention grid: first order month per user, then months-since-first as the column, and verify that month zero equals the cohort size exactly.
  • Sessionize the events table under a 30-minute inactivity rule using LAG plus a cumulative sum over a new-session flag.
  • Build a four-step funnel that counts distinct users rather than events at each step, and state the rule you applied to a user who reaches step three without ever logging step two.

Deliverable: One file with the retention, sessionization and funnel patterns, each carrying a one-line note on the assumption it bakes in.

Day 5 — Write SQL the way you will have to write it live

  • Set a 12-minute timer and solve three medium prompts in a plain editor with no execution and no autocomplete, then run them and tally syntax errors separately from logic errors.
  • Narrate one solution aloud while writing it, stating the grain of each intermediate result (one row per user, one row per user-day) before you type its body.
  • Rewrite your slowest solution as a CTE chain where every CTE name states its grain, and time yourself re-solving it from blank.

Deliverable: A recording of one narrated solution plus an error tally that separates syntax from logic.

Day 6 — One day for everything that is not SQL

  • Write the preconditions of the two-sample t-test from memory, then check them: independent observations, and a difference in means whose sampling distribution is approximately normal, which at large sample sizes follows from the central limit theorem rather than from normality of the raw values.
  • Write the difference between an odds ratio from logistic regression and a relative risk, and state the condition under which the two are close (low outcome prevalence).
  • Prepare a 90-second answer to "how would you know this model is any good" that names the metric, the baseline you would beat, and the cost of the errors you care about.

Deliverable: One page of notes covering test preconditions, the odds-ratio caveat and the model-quality answer.

Day 7 — Full loop rehearsal

  • Run a 45-minute mock with someone willing to interrupt: 20 minutes of SQL, 15 minutes defining a metric, 10 minutes on a past project.
  • Re-solve from blank the two queries you were slowest on this week and compare the times against day five.
  • Write a five-line answer to "walk me through a project" that puts a number in the first sentence and names the decision the work changed.

Deliverable: Mock feedback notes plus a timed project narrative you can deliver without reading it.

The project you argued against

Saying no well is a senior skill and it is rarely rehearsed. Think of a time you told someone their analysis was not worth doing, or that the experiment could not answer their question at the sample size available. Explain what you offered instead. Refusal without an alternative reads as obstruction rather than judgement.

Describe a time you had to optimize a model for performance and scalability.

Medium · behavioural and stakeholder questions

Approach

  1. Pick a story where you drove the decision, not one where you observed it.
  2. Name the disagreement or constraint, and how you resolved it with evidence.
  3. Quantify the outcome, including what you would not claim credit for.

Follow-up

  • How did you know the outcome was caused by your change?
  • What would you do differently if you ran that project again?

How do you explain technical findings to non-technical stakeholders?

Medium · behavioural and stakeholder questions

Approach

  1. Name the disagreement or constraint, and how you resolved it with evidence.
  2. Close with what you would do differently, concretely.
  3. Pick a story where you drove the decision, not one where you observed it.

Follow-up

  • What did you decide not to do, and why?
  • How did you know the outcome was caused by your change?

Explain an incomplete cost series to a non-technical executive

Medium · claims runout · uncertainty · executive communication

An executive opens a dashboard showing risk-adjusted allowed PMPM down 6 percent across the last three incurred months and asks whether the cost initiative is working. You know pharmacy adjudicates within days, professional claims within weeks, and inpatient facility claims over months, so those three months are both undercounted and mix-shifted toward cheap services. There is also a genuine movement of roughly 1.5 percent in the older, complete months. Deliverable: a two-minute spoken answer, the change you make to the chart, and what you commit to telling them and when.

Approach

  1. The probe is whether you can be honest about uncertainty without sounding evasive. Executives read hedging as not knowing, so the answer has to end in a commitment.
  2. Separate the two claims immediately. The 6 percent is an artefact of incomplete data, and there is a smaller real movement in the months that are complete. Delivering only the debunk leaves them holding nothing.
  3. Explain the lag in their terms: the bills for the most expensive care arrive last, so an incomplete month always looks cheap and always looks like it is improving. Keep the phrase completion factor out of the first pass.
  4. Fix the chart instead of explaining around it. Shade or omit the incomplete months, print the paid-through date on the axis, and overlay the same series as it looked at equivalent maturity a year earlier so the shape is comparable rather than merely lower.
  5. Close with a date and a magnitude. Commit to a restated figure once runout matures, say roughly how far you expect the 6 percent to shrink, and name what you would need to see to call the initiative working.

Follow-up

  • They ask for your best guess today, knowing it is provisional. What do you say?
  • The restated number comes back at 1 percent. How do you handle having flagged the 6 percent at all?
  • How do you stop this dashboard producing the same conversation next quarter?