cswork / libraryOpen practice workspace

Interview guides · Nestle Health Science

Nestle Health Science Data Scientist Interview Questions & Guide 2026

Data scientist interview prep for Nestle Health Science: original practice on experiment design, SQL and metric reasoning, with worked solutions.

The 60-second brief

This guide covers what a Data Scientist at Nestle Health Science is expected to do and how to prepare for the interview.

Most of the loop measures decision-making under uncertainty rather than recall. You are scored on whether you state your assumptions, commit to an estimate you can defend, and say explicitly what evidence would change it.

Focus areas

  • Risk-adjust outcomes before comparing providers or panels
  • Correct for claims runout before reporting recent months
  • Separate censoring from events in time-to-event models

The Nestle Health Science interview process

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

Initial Screening Call

Data Scientist covers at least four different jobs: experimentation, product analytics, causal work on observational data, and applied modelling that ships into a system. A screening call is the cheapest place to find out which of them is being hired for, and doing that diagnosis openly reads as senior rather than fussy. Ask what the last few pieces of work on the team actually were, and roughly how a week splits between querying, modelling and stakeholder time. Then say which parts of that you have done and which you have not. Claiming the whole range is the fastest way to be caught one round later.

What to demonstrate

  • Whether you can distinguish the flavours of the role and locate your own experience inside one of them honestly
  • Whether you name what you have not done instead of stretching to cover every line of the posting
  • Whether your hard constraints (notice period, location, work authorisation, level) surface now rather than at offer stage

How to prepare

  • Map the last two years of your time into rough percentages across query writing, experiment design, modelling and stakeholder work, so a question about scope has a real answer
  • Mark every responsibility in the posting as done, adjacent or new, and prepare one sentence for each adjacent item naming the closest thing you have actually built
  • Decide which logistics are non-negotiable before the call so you can state them in one sentence rather than negotiating live

Technical Interviews

Before anything else, this round is a reading test. You are given a small schema and a question phrased in business language, and most of the difficulty sits in the gap between them. Who counts as an active user, does a refunded order still count as an order, is that date column an event time or a load time. Weak answers start typing immediately and compute something precise about the wrong population. Strong ones pin the definition in one sentence, name the column that encodes it, then write the query. On a timed assessment with nobody to tell, write the definition in a comment anyway.

What to demonstrate

  • Whether an ambiguous term becomes a specific column and filter before any computation happens
  • Whether you read the schema for keys and cardinality rather than only for column names
  • Whether the result answers the question at the grain it was asked at, per user or per session or per day

How to prepare

  • Take three metrics you already use and write down the exact filter and exact grain behind each, then practise stating one of them in a single sentence out loud
  • On a schema you have never seen, spend the first minute writing what one row of each table means and which key it is unique on, then predict which joins can duplicate rows
  • Rehearse a version where the definition changes halfway through, and edit the query you have instead of starting over

Domain-Focused Rounds

An added round often puts you in front of someone outside the core hiring team: a partner engineer, a product owner, a domain expert, sometimes a more senior manager. The question they are really asking is not whether you can do the work but whether they would trust a number that came from you. That changes what a good answer looks like. Lead with what the decision cost and what it changed, keep the method available but not central, and be plain about the limits of your evidence. Overstating a result is the fastest way to lose this round.

What to demonstrate

  • Whether you can explain a technical choice to someone who will never read your code, without either flattening it into nothing or hiding inside jargon
  • Honesty about evidence strength: what the analysis establishes, what it only suggests, and what it cannot say at all
  • How you take disagreement, specifically whether you update on a good objection, hold your position with reasons, or fold on contact

How to prepare

  • Write the two-sentence version of your most technical project for a non-specialist, then check that neither sentence needs a method name to make sense.
  • For one result you are proud of, write the strongest objection someone could raise and a response that concedes the part of it that is correct.
  • Prepare one decision that turned out to be wrong: how you found out, what it cost, and what you changed afterwards. A senior cross-functional interviewer asks for this more often than a technical one does.

Where candidates lose points

Ignoring clustering by provider, facility, or site

Patients within a provider panel, and subjects within a trial site, are correlated on both case mix and practice pattern. Standard errors computed as if observations were independent are too narrow by roughly the design effect, 1 + (m - 1) * ICC, where m is the average cluster size. With 50 patients per provider and an intracluster correlation of only 0.02, variance is understated by about a factor of two, which manufactures significant provider differences out of noise. Cluster-robust errors or a random intercept per provider, and cluster-level randomisation when you design the test, are the corrections.

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.

Treating a non-significant result as proof of no effect

Say whether the confidence interval excludes the effect sizes you would have cared about. If it does not, the honest reading is that the test was underpowered, so report the minimum detectable effect the design could have found and what sample size would resolve it.

Defining the cohort on a post-treatment condition

Ask how rows entered the table. Filtering on something that treatment itself influences, such as users who finished onboarding or accounts still active at ninety days, breaks comparability between arms; define the population at an entry point that precedes exposure and keep everyone in it.

Questions & practice

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.

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?

Proportion of days covered with shifted, truncated refill intervals

Hard · interval merging · adherence · path dependence

pharmacy_claim has fill_id, member_id, therapeutic_class_code, fill_date, days_supply, reversal_flag, reversed_fill_id. For one therapeutic class and a fixed 12-month window, compute proportion of days covered per member: distinct days on which a dispensed days_supply covers the day, divided by days from the member's first in-window fill through the window end. An early refill shifts coverage forward rather than stacking, and coverage is truncated at the window end. Drop both rows of every reversed pair. Return member_id, pdc, and the share at pdc >= 0.80 among members with at least 2 fills and at least 91 days of follow-up.

Approach

  1. Remove reversals as pairs first. Drop every row with reversal_flag true, and also drop the fill_ids those rows point at through reversed_fill_id. Dropping only the flagged row leaves a dispense that was never collected in the exposure.
  2. Walk fills per member in fill_date order carrying a cursor: start = max(fill_date, previous_end + 1 day), end = start + days_supply - 1. The shift is path dependent, so a plain cumsum over days_supply does not reproduce it. Use itertools.accumulate or a per-member loop over numpy arrays, not a row-wise apply over the whole frame.
  3. Truncate the last interval at the window end before measuring. Without truncation a 90-day fill dispensed on the final day pushes the covered-day count past the denominator and PDC above 1.0.
  4. Use the denominator the definition states: first in-window fill_date through window end, inclusive. Not a flat 365, and not first fill to last fill, which is a different metric that rewards early discontinuation.
  5. Apply the eligibility filter before computing the >= 0.80 share, and report the size of that denominator next to the share. A share without its denominator is not reviewable.

Follow-up

  • How does PDC differ from medication possession ratio, and which of the two can exceed 1.0?
  • A member switches to a different ingredient inside the same therapeutic class mid-window. Should the intervals chain, and what does that do to the class-level number?
  • Members who die or lose coverage mid-window get a short denominator and often a high PDC. If you then compare mortality by adherence category, what bias have you built in and how do you remove it?

Bootstrap a confidence interval for a ratio-of-sums PMPM

Medium · bootstrap · ratio estimator · resampling unit

You have one row per member for a fully run-out incurred year: member_id, member_months, allowed_amount. Report allowed PMPM, defined as sum(allowed_amount) divided by sum(member_months), with a 95 percent confidence interval from a bootstrap you write yourself. No library resampler. Resample members with replacement, recompute the ratio on each of 2,000 replicates, take a percentile interval, and seed the generator so the result reproduces. In two sentences, state why resampling claim lines instead of members would be wrong.

Approach

  1. Name the estimator precisely: PMPM is a ratio of sums, not the mean of per-member ratios. The two differ whenever exposure correlates with spend, and it does, because members who churn out mid-year are systematically different from members covered all twelve months.
  2. Resample the unit of independence, which is the member, and recompute numerator and denominator together on the same draw. Recomputing only the numerator against a fixed denominator understates variance and is a common slip.
  3. Pull member_months and allowed_amount into numpy arrays once, then draw indices with rng.integers(0, n, size=n) per replicate. Index draws over arrays run one to two orders of magnitude faster than DataFrame.sample, which is the difference between 2,000 replicates and 200.
  4. Take the 2.5th and 97.5th percentiles of the replicate ratios. Expect an interval that is asymmetric around the point estimate, because healthcare spend is right skewed. That asymmetry is the method working, not a bug to centre away.
  5. Answer the line-resampling question concretely: the many lines of one high-cost member are not independent draws, so line resampling shrinks the interval toward zero width, and member_months has no line-level analogue, so the denominator becomes undefined.

Worked solution (25 min)

  1. Compute the point estimate as allowed.sum() / months.sum() on the full sample.
  2. Extract both columns to float numpy arrays and create rng = np.random.default_rng(seed).
  3. Loop 2,000 times: idx = rng.integers(0, n, n); ratio = allowed[idx].sum() / months[idx].sum(); store it.
  4. Take np.percentile(replicates, [2.5, 97.5]) and report the point estimate with that interval and the seed.

Expected result: A point estimate plus a 95 percent percentile interval that is wider on the upper side than the lower. With tens of thousands of members and a typical commercial cost distribution the relative half-width lands on the order of a few percent; an interval a small fraction of a percent wide is the signature of having resampled rows rather than members.

Verify it yourself

  • Re-running with the same seed reproduces both bounds exactly.
  • Raising replicates from 2,000 to 8,000 moves each bound by less than its third significant figure.
  • The mean of the replicate ratios sits close to the point estimate; a large gap indicates a bug in the resampler rather than skew.
  • Replicate denominators cluster tightly around the observed total member-months, which confirms the draw size is n rather than a fixed constant.

Follow-up

  • Half a percent of members have a transplant or a long NICU stay. Does a percentile interval still have nominal coverage, and what would you do about the tail?
  • The question changes to comparing PMPM across provider panels. What becomes the resampling unit and why?
  • How would you use the same replicates to test whether this year's PMPM differs from last year's, given the same members appear in both?

Write a query using SQL window functions to calculate a rolling average of sales over the last 30 days.

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. Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.

Follow-up

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

Explain the difference between various types of joins when merging patient health records.

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. Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.

Follow-up

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

How do you optimize a query that is running too slowly on a large dataset?

Medium · sql and data manipulation

Approach

  1. Say which table is the grain you start from, and join outward from it.
  2. Compute rates by summing numerator and denominator separately, never by averaging rates.
  3. Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.

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?

Deduplicate claim versions before totalling allowed amounts

Easy · dedup · window functions · claim versions

medical_claim_line holds one row per service line per claim version: claim_line_id, claim_id, claim_version, frequency_code (1 original, 7 replacement, 8 void), member_id, service_start_date, procedure_code, allowed_amount, claim_status and adjudicated_at. Adjusted claims appear more than once, so summing every row double counts them. Return total allowed_amount by procedure_code for service_start_date in Q1 2025, counting only lines with claim_status 'paid' on the surviving version of each claim, which is the highest claim_version per claim_id, and dropping the claim entirely when that surviving version carries frequency_code 8. Resolve survivorship with a window function, not a self-join.

Approach

  1. Resolve survivorship at claim_id, not claim_line_id. Carry MAX(claim_version) OVER (PARTITION BY claim_id) alongside every line and keep lines where claim_version equals it, because a replacement version can contain a different number of lines than the original.
  2. Read the frequency_code of the surviving version only. A frequency_code 8 removes the claim outright; it does not revert payment to the prior version, so a void must delete the claim rather than promote version n-1.
  3. Apply claim_status and the date filter after survivorship is resolved. Filtering paid lines first can strip the surviving version and silently elect a superseded one.
  4. Group by procedure_code and sum allowed_amount, then state the paid-through date on the output because Q1 amounts keep moving until adjudication runout completes.
  5. Sanity check the shrinkage: report how many claim_ids and how many dollars the dedup removed, so the reviewer can see the step did something.

Worked solution (20 min)

  1. Build a CTE that adds surviving_version = MAX(claim_version) OVER (PARTITION BY claim_id) and surviving_freq = the frequency_code of the row at that version, to every line.
  2. Filter to claim_version = surviving_version so all lines of the surviving version survive together.
  3. Drop claims whose surviving_freq is 8, then apply claim_status = 'paid' and service_start_date between 2025-01-01 and 2025-03-31.
  4. Group by procedure_code, sum allowed_amount, and emit the count of distinct claim_ids contributing.
  5. Run the naive SUM over all rows beside it and report the difference as the double count that was removed.

Expected result: One row per procedure_code with summed allowed_amount over surviving, non-voided, paid Q1 2025 lines. A claim with an original and one replacement contributes only the replacement's lines; a claim whose surviving version is a void contributes nothing.

Verify it yourself

  • Deduped total is strictly below the naive paid-and-Q1 SUM taken across all versions whenever at least one claim carries paid Q1 lines on more than one version. If the two totals match on such a claim, the dedup did nothing.
  • For one claim_id known to have three versions, the line count it contributes equals the number of its paid Q1 2025 lines at its highest claim_version, not 1.
  • Let B be the set of claim_ids whose surviving version has at least one paid line with a Q1 2025 service_start_date. COUNT(DISTINCT claim_id) in the output equals the size of B minus the number of claims in B whose surviving version carries frequency_code 8. Comparing instead against COUNT(DISTINCT claim_id) over the whole raw table is not a void test: that gap also absorbs every claim dropped by claim_status or by service date.

Follow-up

  • Two rows share a claim_id and claim_version but differ on adjudicated_at. What do you do, and what does that imply about the extract?
  • How does the query change if the request is allowed_amount by paid_date rather than service_start_date, and which basis does a finance reconciliation want?
  • A void arrives for a claim already published in a closed month. How do you restate without rewriting history in the warehouse?

How do you balance long-term health outcomes with short-term user retention metrics?

Medium · product sense and metrics

Approach

  1. State what result would change your recommendation, so the answer is falsifiable.
  2. Fix the population and the time window before naming any metric.
  3. Decompose the metric into the rates that drive it, and say which one you would check first.

Follow-up

  • How would you detect that the metric is being gamed rather than genuinely improving?
  • What would you do if the primary metric and the guardrail moved in opposite directions?

If you notice a sudden drop in a key user engagement metric, what steps do you take to diagnose the root cause?

Medium · product sense and metrics

Approach

  1. State what result would change your recommendation, so the answer is falsifiable.
  2. Name one primary metric, then the guardrail that stops it being gamed.
  3. Fix the population and the time window before naming any metric.

Follow-up

  • How would you detect that the metric is being gamed rather than genuinely improving?
  • What would you do if the primary metric and the guardrail moved in opposite directions?

How would you design a metric to measure the success of a new nutritional product launch?

Medium · product sense and metrics

Approach

  1. Name one primary metric, then the guardrail that stops it being gamed.
  2. Decompose the metric into the rates that drive it, and say which one you would check first.
  3. State what result would change your recommendation, so the answer is falsifiable.

Follow-up

  • How would you detect that the metric is being gamed rather than genuinely improving?
  • Which segment would you cut first, and what would that rule out?

What are the most common experimentation pitfalls you have encountered in previous roles?

Medium · a/b testing and experimentation

Approach

  1. State the primary metric and the minimum effect worth shipping, then size the test.
  2. Say whether units interfere with each other, and switch design if they do.
  3. Name the randomisation unit first; it decides the variance and what the test can detect.

Follow-up

  • What would you do if you could not randomise at all?
  • How would you handle interference between treated and control units?

Explain how you would handle an A/B test where the treatment and control groups are not perfectly balanced.

Medium · a/b testing and experimentation

Approach

  1. Name the randomisation unit first; it decides the variance and what the test can detect.
  2. Say whether units interfere with each other, and switch design if they do.
  3. State the primary metric and the minimum effect worth shipping, then size the test.

Follow-up

  • What would you do if you could not randomise at all?
  • What would you conclude if the result is positive but the test is underpowered?

Score trial sites without rewarding enrollment that does not stick

Medium · site scorecards · shrinkage · guardrails · gaming

A clinical operations group ranks sites on subjects randomized per activated site-month, using study_subject_visit (study_id, site_id, subject_id, arm_code, randomization_ts, site_activation_date, visit_name, visit_number, visit_status, primary_endpoint_value, protocol_deviation_flag, deviation_severity). Bottom-ranked sites lose allocation on the next study. Define the primary metric, two guardrails, the handling of sites activated too recently to rank, and the estimator you rank on. Then state what a site under allocation pressure does to the number, and which guardrail sees it.

Approach

  1. Move the numerator from randomized to randomized and retained through the protocol-defined primary endpoint visit. A subject who randomizes and withdraws consumes screening, drug supply and monitoring while contributing nothing to the analysis population, so counting them rewards the wrong behaviour precisely when a site is under pressure.
  2. Build the denominator as exposure, not sites: site-months from site_activation_date to the earlier of period end and database lock, per study. Ranking on a raw count instead of a rate confuses a large site with a fast one.
  3. Handle young sites by reporting rather than dropping. Sites with fewer than a stated minimum exposure are shown in an insufficient-exposure band, because excluding them is how a non-enrolling tail disappears from a scorecard, and the non-enrolling tail is usually the larger operational problem.
  4. Rank on a shrunken estimate, not the raw ratio. With a few site-months of exposure the ratio has enormous variance, and a site with two site-months and one randomization will top an unshrunken table. Partial pooling toward the study mean, or a simple empirical-Bayes posterior mean, prevents rank being an artefact of small exposure.
  5. Pick guardrails that read the two pressure responses. A site that loosens eligibility judgement shows an implausibly low screen-failure rate, computed as subjects with randomization_ts NULL and visit_status screen_failed over subjects screened. A site that pushes visits to hit counts shows up in major protocol deviations per 100 completed visits, reported separately from minor ones because a single major deviation can remove a subject from the per-protocol set.
  6. Report the companion the median hides: the share of activated sites with no randomization by day 90. A median computed only over sites that eventually randomized is silent about the sites that never did.

Worked solution (30 min)

  1. Define the numerator as subjects with non-null randomization_ts whose primary endpoint visit reaches visit_status completed with a non-null primary_endpoint_value, per study and site.
  2. Compute site-months of exposure from site_activation_date to period end or database lock, and set the minimum exposure below which a site is banded rather than ranked.
  3. Compute the raw rate, then the shrunken estimate by partial pooling toward the study mean, and print both columns side by side so the shrinkage is visible rather than hidden.
  4. Specify the two guardrails with numerator, denominator and window, keeping major and minor deviations as separate series.
  5. Add the no-randomization-by-day-90 share across all activated sites, so the non-enrolling tail appears on the same page as the ranking.

Expected result: A scorecard whose primary metric is randomized-and-retained subjects per activated site-month per study, ranked on a shrunken estimate with the raw rate shown beside it; sites below a stated minimum exposure reported in an insufficient-exposure band rather than excluded; guardrails of screen-failure rate and major protocol deviations per 100 completed visits reported separately from minor ones; and a companion share of activated sites with no randomization by day 90.

Verify it yourself

  • Compare raw and shrunken rankings. The largest rank movements should be concentrated among the lowest-exposure sites; if a high-exposure site moves far, the pooling is misconfigured.
  • Confirm the denominator's site-months sum matches an independent count of months between activation and period end across all sites.
  • Check that screen failures are being counted at all: a site reporting a zero screen-failure rate across dozens of screened subjects is a data-capture problem or an eligibility-judgement problem, and both need an answer.
  • Verify that excluding the insufficient-exposure band does not change the study-level mean materially; if it does, those sites carry more of the study than the banding implies.

Follow-up

  • A site has the best randomized-and-retained rate and the worst major deviation rate. What do you recommend, and what would change your answer?
  • Your shrunken ranking moves a site from 3rd to 14th. How do you explain shrinkage to the site's operations lead in two sentences?
  • Primary endpoint retention takes 18 months to observe. What do you rank on in the meantime, and what bias does that interim choice introduce?

Allowed PMPM fell fourteen percent in three months

Easy · claims runout · completion factors · incurred vs paid

Allowed PMPM in the monthly series fell from $412 to $354 over the three most recent incurred months, and leadership wants to announce the saving. You have medical_claim_line (allowed_amount, service_start_date, received_date, paid_date, claim_id, claim_version, frequency_code, place_of_service_code), pharmacy_claim (allowed_amount, fill_date, reversal_flag) and member_enrollment coverage spans. The chart carries no paid-through date. Work out how much of the fall survives completion, and hand back a restated series with an explicit paid-through date and the completion factors you applied.

Approach

  1. Get the paid-through date first and put it on the chart. Without it the series is uninterpretable, because every incurred month is a different age.
  2. Build a lag triangle: for each incurred month, cumulative allowed_amount by the number of months between service_start_date and paid_date, on surviving claim versions only (drop frequency_code 8 voids and keep the highest claim_version per claim_id).
  3. Estimate development factors separately for pharmacy fills, professional lines and inpatient facility lines. Pharmacy adjudicates within days, professional within weeks, inpatient facility over months, so one blended factor understates the correction on the newest month and overstates it on the oldest.
  4. Gross each of the last three incurred months up by the reciprocal of its cumulative development factor, using factors fitted on months that have already fully run out.
  5. Rebuild the denominator independently as member-months from coverage spans. Member-months are complete on day one, so if the denominator also shows a lag pattern the enrollment file is late, which is a different bug with a different fix.
  6. Restate the series, mark the last three months as estimated, and report the residual movement after completion as the only part worth investigating.

Follow-up

  • The completed series still shows a three percent fall. What do you look at next, and in what order?
  • How would you detect that the fall is a mix shift toward cheaper services rather than lower volume?
  • A contract settles on this number at a fixed paid-through date. What do you owe the other party about the estimate you just made?

Suggested practice checklist

Instead of guessing where the week should go, day one measures it under a fixed rubric and allocates the remaining hours in proportion to the gaps. The method is deliberately rigid: the allocation is written down before any studying starts and is not renegotiated when a topic turns out to be unpleasant.

Day 1 — Diagnostic, scored before you study anything

  • Sit a 100-minute timed diagnostic in four blocks: 30 minutes of SQL across three prompts, 25 minutes of short-answer statistics, 25 minutes on one modelling or case prompt, and 20 minutes delivering one behavioural story aloud.
  • Score each block from 0 to 3 on a fixed rubric where 3 is correct and fluent, 2 is correct but slow or prompted, 1 is partially correct, and 0 is stuck, grading the output rather than how the attempt felt.
  • Allocate the hours for days two to five roughly in proportion to 3 minus the score in each block, write the allocation down, and commit to not revising it midweek.

Deliverable: A scored rubric and a fixed hour allocation for the rest of the week.

Day 2 — Largest gap: find the boundary rather than the subject

  • Break the weakest area into five named sub-skills (for query work: grain control, window frames, date arithmetic, set logic with NULLs, and reading a query plan) and rate each one, so the rest of the week targets a sub-skill instead of a subject.
  • Solve three problems chosen to sit just above where the rating drops off, and for each write the first move you failed to make.
  • Re-solve one of them from memory four hours later, on paper, with nothing open.

Deliverable: A five-item sub-skill map with the two blocking sub-skills circled.

Day 3 — Largest gap: drill the blocking sub-skill

  • Do eight short repetitions of the same shape rather than eight different problems, so what you practise is the pattern and not the puzzle.
  • Write the rule you now hold in one sentence, then test it against a case built to break it: a ranking function over a column with ties, or a two-sample test on observations that are obviously dependent.
  • Have someone else read your one-sentence rule and find the precondition you left out.

Deliverable: One rule statement with its preconditions attached and one counterexample that would have caught the incomplete version.

Day 4 — Second gap, plus maintenance on your strongest area

  • Run the same sub-skill map and boundary protocol on the second-largest gap, compressed into half the day.
  • Spend 25 timed minutes on your strongest area to stop it decaying, choosing the hardest problem you can still finish rather than an easy warm-up.
  • Compare how the two areas fail: whether you lose time on recall, on setup, or on arithmetic, because the fix differs for each.

Deliverable: A second sub-skill map plus a one-line diagnosis of how each area fails you.

Day 5 — The gap that is not a skill

  • Record yourself answering one technical and one behavioural prompt, then count two things in the playback: how many seconds before your first clarifying question, and how many sentences you started without knowing where they ended.
  • Rewrite your three most-used stock phrases into shorter versions, and practise saying "I do not know, here is how I would find out" without softening it into a guess.
  • Deliver one answer again with a hard 90-second limit to force structure before detail.

Deliverable: Two recordings with a counted improvement in time-to-first-question.

Day 6 — Retest under day-one conditions

  • Sit the same 100-minute diagnostic structure with new prompts of comparable difficulty and score it on the identical rubric.
  • Compare block by block, and for any block that did not move, change the method rather than adding hours: a block stuck at 1 usually means the practice was too varied, not too short.
  • Write which single block you would still lose the offer on.

Deliverable: A second scored rubric placed next to the first, with one named remaining risk.

Day 7 — Full loop under interview conditions

  • Run a 60-minute mock covering the two blocks that moved least, with an interviewer instructed to interrupt and change direction.
  • Write your recovery script for the moment you go blank: restate the question, state your assumption, name the first thing you would check.
  • Reduce the week to the rule statements you wrote, each with its preconditions attached, then say every one of them out loud without reading it and cut any you cannot state in a single sentence, since a rule you have to reconstruct mid-answer will not survive being interrupted.

Deliverable: A one-page card holding the recovery script and only the rules you could state from memory.

Getting an analysis acted on

Work that nobody used is a common and unflattering pattern in data careers, and interviewers probe for it. Have a story about an analysis that changed a decision, and be specific about how you got it in front of the person who could act. Also have one about work that went nowhere, with your reading of why.

Describe a time you had to explain a complex technical finding to a non-technical manager.

Medium · behavioural and stakeholder questions

Approach

  1. State the situation in two sentences and spend the rest on your reasoning.
  2. Pick a story where you drove the decision, not one where you observed it.
  3. Name the disagreement or constraint, and how you resolved it with evidence.

Follow-up

  • What did you decide not to do, and why?
  • What would you do differently if you ran that project again?

Push back on an over-broad extract without blocking the work

Hard · minimum necessary · de-identification · governance

A researcher asks for a one-off extract covering 12,000 members: member_id, date of birth, five-digit residential postal code, full lab_result rows including value_text, and clinical note text, held on their laptop for a retrospective analysis of one lab analyte over time. They describe it as de-identified because names are excluded. A flat refusal is not an acceptable answer. Deliverable: the column list you will actually provide with a justification per retained field, the sentence explaining why free text defeats an enumerated-identifier approach, your small-cell rule for the published stratification, and what you deliver this week.

Approach

  1. The probe is whether privacy is a design skill for you or a compliance reflex. Flat refusal and unquestioned fulfilment both fail, for opposite reasons.
  2. Reconstruct the analysis from the research question rather than from the request. A longitudinal trend in one analyte needs a stable pseudonymous subject key, the analyte's loinc_code, value_numeric, units, the reference bounds, and a date. It does not need names, notes, or a precise birth date.
  3. Replace each identifier with the least precise version that still answers the question: a salted per-study pseudonym instead of member_id, age in years or an age band instead of date of birth, a consistent per-subject date offset if only intervals matter, and a coarser geography than five-digit postal code.
  4. Explain the free-text problem in one sentence. Removing an enumerated list of identifier fields does not de-identify a note, because notes carry names, relationships, employers, dates and rare clinical detail in prose, so only a reviewed extraction into structured fields or a formal statistical determination addresses it.
  5. Set the publication rule before the analysis runs. Suppress cells below a stated threshold and suppress complements too, because a reader holding a row total and all but one cell recovers the suppressed count by subtraction.
  6. Keep them moving. Deliver the reduced extract into a controlled environment this week rather than onto a laptop, and offer to derive any note-based variable yourself as a structured flag so they never need the prose.

Follow-up

  • They say the age band loses resolution their model needs. What do you do?
  • How do you set the suppression threshold, and who signs off on it?
  • The analysis later needs linking to a second data source. What changes?

Sequence three urgent requests with one analyst-week available

Medium · prioritisation · tradeoffs · stakeholder communication

Three requests land on Monday and you have one week. An actuarial team needs incurred-claims completion factors restated before a filing deadline on Thursday. A clinical programme owner wants a deterioration model refreshed because its calibration has drifted in one region. A trial operations team wants site enrolment forecasts for a portfolio review in two weeks. Each requester believes theirs is blocking. Deliverable: your sequence with the reasoning, the message you send to whoever is deprioritised, and the smaller artefact you hand each of the two you cannot fully serve.

Approach

  1. The probe is whether you prioritise on consequence and reversibility rather than on who asked loudest or most recently.
  2. Classify each request by what happens if it slips. A regulatory or contractual deadline is irreversible on its date, a drifting model is causing harm every day it keeps running, and a portfolio review can absorb a provisional number. That ordering is defensible to all three requesters because it does not depend on your preferences.
  3. Take the deadline-bound work first, but scope it to the minimum defensible output, because completion factors feeding a filing carry a different error tolerance than a slide.
  4. Do not let the drifting model simply wait. Quantify the harm cheaply by comparing calibration in the affected region against the rest, and if it is materially miscalibrated propose flagging or suppressing its output for that region within the hour rather than at the end of a refresh.
  5. Give each deprioritised requester something real: a provisional forecast with its uncertainty and a refresh date, or a diagnostic that tells them whether their problem is urgent. Say no explicitly with a date rather than going quiet, because silence is what produces escalation.

Follow-up

  • The programme owner escalates to your manager. What do you want your manager to be able to say?
  • Midweek the actuarial work needs two more full days than you estimated. What gives?
  • How does your answer change if the drifting model drives a clinical outreach list rather than a report?