Interview guides · Avid Bioservices
Avid Bioservices Data Scientist Interview Questions & Guide 2026
Avid Bioservices Data Scientist interview guide: reported rounds, practice questions with worked solutions and a 7-day prep plan.
The 60-second brief
As a Data Scientist at Avid Bioservices, you play a pivotal role in the analysis and interpretation of complex data sets that drive critical decision-making processes within the company. Your work directly influences the development and optimization of biopharmaceutical products, ensuring the efficacy and safety of treatments that enhance patient care. This position is essential for translating data into insights that not only shape product development but also impact the overall strategy and direction of the company.
SQL is seldom the hardest round and is often the one that eliminates people. The working bar is usually window functions, correct deduplication, and joins that do not silently fan out rows, rather than obscure syntax.
Focus areas
- Minimise protected health information in every extract
- Correct for claims runout before reporting recent months
- Separate censoring from events in time-to-event models
Overview
The Data Scientist is integral to cross-functional teams, collaborating closely with biologists, chemists, and engineering personnel to provide data-driven insights that enhance operational efficiency and product quality. You will engage in advanced analytics, predictive modeling, and machine learning projects, dealing with large-scale data that can influence significant business outcomes. This role is both challenging and rewarding, offering you the opportunity to work on cutting-edge projects in the biopharmaceutical industry that can make a real difference in people's lives.
The Avid Bioservices interview process
Avid Bioservices candidates report 4 rounds · ≈ 3-5 weeks. The stages below are what candidates describe, not a published process.
HR Screening
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
This round decides whether someone can hand you a schema and a question and trust the number that comes back. Correctness under a clock is the bar, not clever syntax. The habit that separates strong from weak answers is checking the grain: after every join, know how many rows you expect and whether the count moved. Most wrong answers in this format are not wrong logic, they are a fan-out from a key that turned out not to be unique, or a filter applied before an aggregate when it belonged after. Say what you expect before you run it.
What to demonstrate
- Whether your row counts survive each join, and whether you notice on your own when they do not
- Deliberate handling of rows that fail to match, including whether the question needs an inner join or a left join with the non-matches kept and counted
- Whether NULLs are treated on purpose, given that a NULL compares equal to nothing and that COUNT of a column skips it
- Reaching a defensible answer inside the window instead of a refined one after it
How to prepare
- Take a two-table schema, write a join that fans out on purpose, then fix it by collapsing the many-side to one row per key before joining. Repeat until the fix is reflex rather than recall.
- Write a funnel as one query and print the distinct user count at each stage, then confirm each stage is a subset of the one above it rather than assuming it
- Do a few timed runs in a plain text box with no autocomplete and no formatter, since assessment editors often have neither
Assessment
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
Cultural Fit Evaluation
Much of what gets scored here happens out loud while you type. Nobody can see your reasoning inside a half-written query, so five silent minutes read as being stuck even when they are not. State the plan in plain language first: which tables, what grain you are aggregating to, and the one filter that defines the population. Then write it. The narration doubles as insurance, because a wrong plan gets caught early and cheaply while a wrong query gets caught at the end with no time left to redo it. A timed statistics section, where one exists, is a separate test with its own clock.
What to demonstrate
- Whether the query you write matches the plan you just described
- What you do with a hint, meaning whether the correction gets absorbed or the first approach gets defended
- Whether you can debug your own wrong output by reading the result set and naming which part of the query produced the anomaly
How to prepare
- Solve three problems while screen-sharing into a recording, then watch it back and mark every stretch longer than thirty seconds where you said nothing
- Practise compressing the plan into one sentence before typing, then check afterwards whether the finished query actually matched it
- Time yourself on statistics questions that carry a business reading, such as what a confidence interval does and does not claim, rather than re-reading notes without a clock
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.
Reporting a mean for a heavy-tailed metric without saying what it hides
For spend, session length or items per order, a small fraction of units carries most of the total, so the mean has a wide standard error and one account can move it. Fix the handling before you see the result: cap or winsorise at a pre-declared percentile, and report the median or the share above a threshold next to the mean. Capping changes the estimand, so say which question the capped number answers, and check how much of any difference comes from the top 0.1 percent of units.
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
Can you explain the bias-variance tradeoff?
Medium · statistics and probability
Approach
- Write down the assumption the method needs before you use the method.
- Quantify uncertainty explicitly rather than reporting a point estimate alone.
- Translate the result into the decision it informs, in one plain sentence.
Follow-up
- How would you explain this result to someone who does not know statistics?
- What sample size would you need to detect an effect half this size?
Discuss a project where you applied machine learning. What challenges did you face?
Medium · machine learning and modelling
Approach
- Check what information would not exist at prediction time, and exclude it.
- Pick an evaluation metric that matches the cost of each error type, not a default.
- Frame the prediction: the label, the moment of prediction, and the action it triggers.
Follow-up
- How would you choose the decision threshold, and who owns that choice?
- What would you monitor after launch to know the model is still valid?
How do you validate the performance of a model?
Medium · machine learning and modelling
Approach
- Set a baseline first, so any model has something honest to beat.
- Pick an evaluation metric that matches the cost of each error type, not a default.
- Frame the prediction: the label, the moment of prediction, and the action it triggers.
Follow-up
- What would you monitor after launch to know the model is still valid?
- How would you choose the decision threshold, and who owns that choice?
Sessionise transfer chains into episodes, then count readmissions
Hard · sessionisation · cumsum grouping · readmission
encounter has encounter_id, patient_id, facility_id, encounter_type, admit_ts, discharge_ts, admission_type, discharge_disposition, is_planned_admission, principal_diagnosis_code. Chain acute-to-acute transfers into episodes of care: an inpatient encounter discharged as transfer_acute, followed by another inpatient encounter for the same patient at a different facility admitting within 24 hours of that discharge, belongs to the same episode. Then compute the 30-day unplanned readmission rate over episodes, excluding index episodes that are planned, that end in expired, hospice or against medical advice, or that are still open. Return encounter_id to episode_id, plus the rate.
Approach
- Restrict to inpatient encounters for the chaining step and sort by patient_id, admit_ts. Observation and emergency encounters are not acute inpatient stays and pooling them changes both the chain and the denominator.
- Build a boolean continues flag: the previous row is the same patient, its discharge_disposition is transfer_acute, its facility_id differs from this row's, and admit_ts minus previous discharge_ts is between 0 and 24 hours. Episode id = cumsum of the negation of that flag. This is the vectorised form of a sessionisation loop and is why the pattern generalises to any event stream.
- Collapse to episode grain taking first admit_ts, last discharge_ts, last discharge_disposition, and any() of is_planned_admission. The episode inherits its exit state, not its entry state, which is why a transfer chain ending at home is one home discharge rather than two transfers.
- Apply index exclusions at episode grain. Dropping episodes that end in death is not optional: a dead patient cannot be readmitted, so leaving them in inflates the denominator and depresses the rate for exactly the panels caring for the sickest members.
- For each surviving index episode, find the next unplanned acute inpatient episode for that patient admitting within 30 days of the index discharge_ts. Count events at episode grain, since one patient can contribute several index episodes. Report the raw rate and say plainly that it is not comparable across panels without risk adjustment, which is what the observed-over-expected form exists for.
Worked solution (45 min)
- Filter to encounter_type 'inpatient', sort by patient_id and admit_ts, and shift discharge_ts, discharge_disposition, facility_id and patient_id by one row.
- Compute continues as same patient AND prior disposition is transfer_acute AND facility differs AND 0 <= (admit_ts - prior discharge_ts) <= 24 hours; episode_id = (~continues).cumsum().
- Aggregate to episodes: first admit_ts, last discharge_ts, last discharge_disposition, any planned flag, patient_id.
- Drop index-ineligible episodes: planned, disposition in expired, hospice or ama, and null discharge_ts.
- For each eligible index episode, search the same patient's later episodes for an unplanned admit_ts within 30 days of index discharge_ts; a merge_asof on patient with a forward direction and a 30-day tolerance does this without a nested loop.
- Rate = index episodes with an event divided by eligible index episodes; return the encounter-to-episode map alongside it.
Expected result: Two outputs: an encounter_id to episode_id map, and one rate. Worked case: encounter A discharged transfer_acute at 10:00, encounter B admitted 14:00 the same day at a different facility and discharged home on day 5, encounter C an unplanned admission on day 20. A and B form one episode, C is a readmission of it, and the patient contributes one eligible index episode and one event, not two indexes and possibly two events.
Verify it yourself
- Every closed episode ends in a disposition other than transfer_acute; an episode ending in transfer_acute means a chain was cut early.
- Episode count is less than or equal to inpatient encounter count, with equality only when the sample contains no transfers.
- Turning the chaining rule off raises the readmission rate. The direction of that change is the proof your chaining fired at all.
- No index episode's matched readmission is an encounter already inside that same episode.
Follow-up
- discharge_ts is null on an open stay in the middle of a chain. What does your flag do, and what should it do?
- A patient is transferred out and then back to the originating facility within 24 hours. Should that chain, and does your facility_id condition handle it?
- Is a readmission itself eligible to serve as a later index episode? Say what you chose and what the choice does to the rate.
Write a function to remove duplicates from a list.
Medium · sql and data manipulation
Approach
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
- Say which table is the grain you start from, and join outward from it.
- 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?
How do you optimize the performance of a SQL query?
Medium · sql and data manipulation
Approach
- Compute rates by summing numerator and denominator separately, never by averaging rates.
- State the window function and its partition and ordering out loud before writing it.
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
Follow-up
- How would you verify this result without re-running the same query?
- What breaks if events arrive late or out of order?
Explain the difference between supervised and unsupervised learning with examples.
Medium · sql and data manipulation
Approach
- Compute rates by summing numerator and denominator separately, never by averaging rates.
- Check whether any join is one-to-many before aggregating, or the sums inflate.
- State the window function and its partition and ordering out loud before writing it.
Follow-up
- How does the query change if the join becomes one-to-many?
- What breaks if events arrive late or out of order?
Reconstruct drug coverage intervals and compute proportion of days covered
Hard · gaps and islands · window functions · adherence
pharmacy_claim holds fill_id, member_id, ndc_code, therapeutic_class_code, fill_date, days_supply, reversal_flag and reversed_fill_id. Early refills overlap, so days_supply must be laid end to end: each fill's coverage starts at the later of its fill_date and the previous interval's end. Both rows of a reversed pair are excluded. For one therapeutic_class_code over 2025-01-01 to 2025-06-30, return per member the proportion of days covered, defined as covered days divided by days from first fill_date to window end, plus the share of members at or above 0.80. Require at least two fills and 91 days of follow-up.
Approach
- Clean the fills first. Drop rows with reversal_flag TRUE and also the fills they point at through reversed_fill_id. Dropping only the reversal row leaves an original fill counted as exposure that never reached the member. Use NOT EXISTS for that second step, since reversed_fill_id is nullable and NOT IN would return nothing.
- Shift, never stack. The shifted end is covered_end_i = GREATEST(fill_date_i, covered_end_{i-1}) + days_supply_i, which looks recursive but has a closed form: with cum_i the running sum of days_supply through fill i, covered_end_i = cum_i + MAX over j <= i of (fill_date_j - cum_{j-1}). That is SUM(days_supply) OVER (ORDER BY fill_date ROWS UNBOUNDED PRECEDING) plus a running MAX of an anchor column, so it is two window functions and no recursive CTE.
- Derive covered_start_i as GREATEST(fill_date_i, LAG(covered_end)). The intervals are disjoint by construction, so covered days is a plain sum of lengths and never needs a distinct day grid.
- Clip intervals to the window end before summing, and decide explicitly whether to clip at disenrollment as well. Supply that runs past the window must not inflate the numerator.
- Use the denominator the spec names, first fill_date to window end, and hold it constant across classes. A fixed-window denominator yields a different and usually lower number, and mixing the two across classes makes the comparison meaningless.
- Apply the inclusion rules at member level after the intervals are built, then compute the share at or above 0.80 with the qualifying member count beside it.
Worked solution (40 min)
- Filter to the therapeutic_class_code and window, then remove reversal rows and their originals with NOT EXISTS.
- Per member ordered by fill_date, compute cum_supply and anchor = fill_date - (cum_supply - days_supply), then covered_end = cum_supply + MAX(anchor) OVER (ORDER BY fill_date ROWS UNBOUNDED PRECEDING).
- Compute covered_start = GREATEST(fill_date, LAG(covered_end) OVER (ORDER BY fill_date)), clip both ends to the window, and drop intervals that collapse.
- Sum interval lengths as covered_days, compute follow_up_days from first fill_date to window end, and divide.
- Apply the two-fill and 91-day rules, then aggregate the share at or above 0.80.
Expected result: One row per qualifying member with covered_days, follow_up_days and pdc in [0, 1], plus a summary row with qualifying members and the share at or above 0.80. A member with 30-day fills on 2025-01-01, 2025-01-20 and 2025-04-01 is covered 2025-01-01 to 2025-03-01 and 2025-04-01 to 2025-04-30, giving 60 + 30 = 90 covered days over 181 follow-up days and a PDC of 0.497.
Verify it yourself
- No pdc exceeds 1.0 before any clipping. A value above 1 proves supplies were stacked instead of shifted.
- On a twenty-member sample, the summed interval lengths equal the distinct covered day count from a slow day-grid version.
- A member with one fill is excluded by the two-fill rule rather than appearing with a PDC of 1.0.
- Re-running with reversals left in raises covered days for exactly the members who have a reversed_fill_id, and for no one else.
Follow-up
- A member is hospitalised for twelve days mid-window, when the facility supplies medication. Should those days count as covered, and what do published adherence measures do about them?
- Someone wants to classify adherence over twelve months and then compare mortality from month zero. What is wrong with that design and what fixes it?
- Two different ndc_codes in the same therapeutic class overlap. Is that stacking or switching, and how does your interval logic treat each case?
How would you approach a situation where the data suggests a discrepancy in expected outcomes?
Medium · product sense and metrics
Approach
- Decompose the metric into the rates that drive it, and say which one you would check first.
- Name one primary metric, then the guardrail that stops it being gamed.
- Restate the decision this analysis has to support, and who acts on the answer.
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?
Given a dataset from a clinical trial, how would you analyze it to draw meaningful conclusions?
Medium · product sense and metrics
Approach
- Fix the population and the time window before naming any metric.
- Name one primary metric, then the guardrail that stops it being gamed.
- State what result would change your recommendation, so the answer is falsifiable.
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?
What attracts you to work at Avid Bioservices?
Medium
Approach
- Say what you would check first and why it is the highest-information step.
- State your assumptions explicitly before working the problem.
- Clarify what is being asked and what a complete answer would contain.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
Decompose risk-adjusted cost per member into owned leaf metrics
Hard · metric tree · price volume mix · coding intensity · ownership
Build a metric tree, at most four levels deep, from risk-adjusted allowed PMPM down to leaves an owner can move. Data: medical_claim_line (allowed_amount, units, procedure_code, place_of_service_code, service_start_date, claim_version, frequency_code), pharmacy_claim (allowed_amount, days_supply, is_generic, formulary_tier, reversal_flag), member_enrollment (coverage spans, prospective_risk_score). Give the arithmetic identity each split rests on, the leading indicator at each leaf, and identify the one node where the arithmetic is exact but the attribution is not.
Approach
- State the base identity before drawing anything. Allowed PMPM equals total allowed over member-months, and it decomposes exactly by service category c as the sum over c of (units_c / member-months) times (allowed_c / units_c). Utilization per member-month and allowed per unit, summed across categories, so category mix is inside the sum rather than a separate hand-wave.
- Give the change decomposition too, because the tree will be read on deltas: the change in PMPM equals the sum over categories of (change in utilization times base price) plus (base utilization times change in price) plus (change in utilization times change in price). The third term is the interaction, it is not noise, and an analysis that drops it will not reconcile.
- Build the medical branch to leaves with owners: inpatient admits per 1,000 member-months and allowed per admit (with DRG case mix as the sub-split), ambulatory visits per 1,000 and allowed per visit split by place_of_service_code, and emergency visits per 1,000 and allowed per visit. Prepare the data with version dedup to the surviving claim_version before a single dollar is summed, since frequency_code 7 replaces and 8 voids.
- Build the pharmacy branch on 30-day equivalents: scripts_30 equals the sum of days_supply over 30 on unreversed fills, so pharmacy PMPM equals (scripts_30 per member-month) times (allowed per 30-day script). Split the price term exactly as g times the generic price plus (1 minus g) times the brand price, where g is the generic dispensing rate, which makes generic substitution and unit price separable leaves with different owners.
- Attach one leading indicator per leaf: prior-authorization approvals and elective surgical bookings ahead of inpatient admits, contract effective dates ahead of allowed per unit, site-of-service steering ahead of the ambulatory place_of_service mix, new-to-brand starts and formulary tier placement ahead of pharmacy price.
- Name the node where arithmetic is exact but attribution is not: the risk-adjustment denominator. Dividing by the population mean prospective_risk_score is exact arithmetic, but the score is built from coded diagnoses, so more complete coding raises the denominator and lowers risk-adjusted PMPM with no change in care delivered. Carry raw PMPM, the mean risk score trend and a coding-intensity measure such as diagnoses per member-year beside it, permanently.
Worked solution (45 min)
- Write the base identity and the three-term change decomposition on paper first, and confirm the terms sum to the total change on a two-category toy example before touching real data.
- Specify the preparation rules that precede any aggregation: dedup medical_claim_line to the surviving version per claim_id using claim_version and frequency_code, drop both rows of every reversed pharmacy pair, and build member-months from coverage spans with partial months counted fractionally.
- Draw the medical branch and the pharmacy branch to leaf level, writing the identity beneath each split rather than only the metric name.
- Write the generic-dispensing split as the exact price identity and confirm it reproduces the observed allowed per 30-day script.
- Attach one leading indicator and one named owning function to each leaf.
- Write the caveat on the risk-adjustment node, including the two companion series that must be published with it.
Expected result: A four-level tree rooted at risk-adjusted allowed PMPM, splitting by service category into utilization per member-month and allowed per unit, with an inpatient sub-split on DRG case mix, an ambulatory sub-split on place_of_service_code, and a pharmacy branch on 30-day equivalents whose price term is split exactly by generic dispensing rate; each leaf carries a named owner and a leading indicator; and the risk-adjustment denominator is flagged as exact arithmetic with unreliable attribution, published alongside raw PMPM, the mean risk score trend and a coding-intensity series.
Verify it yourself
- Reconcile the leaves back to the root: the summed category contributions must equal total allowed PMPM to within rounding, and the three change terms must sum to the observed period change.
- Recompute total allowed with and without version dedup. Any gap is the double-counted adjusted claims the tree would otherwise attribute to real utilization.
- Verify the pharmacy price identity numerically: generic dispensing rate times generic price plus its complement times brand price should reproduce the observed blended allowed per 30-day script.
- Hold care constant and simulate a 5 percent rise in mean prospective_risk_score. Risk-adjusted PMPM should fall by roughly the same proportion, which is the attribution problem made visible.
Follow-up
- Utilization is flat and allowed per unit is flat, yet PMPM rose 4 percent. Name every place the increase can be hiding.
- Your member-month denominator came from coverage spans that overlap across products for some members. What does that do to PMPM, and how do you decide whether to deduplicate?
- Which leaf would you refuse to put on a team's scorecard, and why?
Avoidable admissions fell the quarter a programme launched
Hard · mix shift · regression to the mean · reclassification · seasonality
Ambulatory care sensitive admissions per 1,000 member-years fell 18 percent in the quarter a care-management programme launched, enrolling the top 2 percent of members by prior-year spend. You have encounter, member_enrollment including a product line added mid-quarter, and medical_claim_line. Emergency visits per 1,000 rose 9 percent over the same quarter and observation stays rose as well. Produce a decomposition that states how much of the 18 percent is attributable to the programme, and state the design you would need before claiming any of it.
Approach
- Rebuild the denominator from coverage spans as member-years, counting partial coverage fractionally, and recompute the rate with and without the product line that entered mid-quarter. A newly added, structurally healthier population inflates the denominator and deflates every rate built on it without a single admission being avoided.
- Freeze the numerator's code list to one version. The ambulatory care sensitive list is defined on ICD-10-CM principal diagnosis codes, and in the United States that code set is updated effective October 1, so a quarter spanning that boundary can gain or lose qualifying codes. Recompute both quarters against a single code set version.
- Decompose the remaining change with a Kitagawa split across product_type and prior-year risk decile: the mix term is the population getting younger or healthier, the within term is the only place a programme effect can live.
- Test reclassification directly. An inpatient stay recorded as an observation stay is not an avoided admission. Compute total acute contacts per 1,000 member-years as inpatient plus observation plus emergency, and check whether that total moved at all. If it is flat while inpatient falls, care was relabelled and deflected, not prevented.
- Compare to the same quarter of the prior year rather than the adjacent quarter. Several ambulatory care sensitive conditions, including heart failure decompensation and bacterial pneumonia, are strongly seasonal, so a quarter-over-quarter comparison confounds the programme with the calendar.
- Address selection last and explicitly. The enrolled cohort was chosen on an extreme of prior-year spend, so it regresses toward the mean with no intervention at all, because the selecting year captured both chronic severity and one-off events. A pre-post design on this cohort will report savings every time. The minimum credible design is a concurrent comparison group selected by the same rule in the same period, or a regression discontinuity at the 2 percent threshold, with a parallel-trends check on at least four pre-periods.
Follow-up
- The parallel-trends check fails on two of the four pre-periods. What do you do, without abandoning the question?
- Express the effect you can defend as an absolute risk difference and a number needed to treat, with the baseline rate stated. Why is that more useful here than a relative reduction?
- The programme cannot be withheld from anyone. Sketch a rollout design that still identifies an effect, and say what secular trend does to the estimate.
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.
Stories where someone disagreed with you
Have two ready. In one, the data was on your side and you had to move someone who outranked you. In the other, the pushback was correct and you changed position. The second is the harder story and it lands better, because it shows you separate being right from being attached to an answer. Name the person's actual objection.
Describe a time when you had to make a decision based on incomplete data.
Medium · behavioural and stakeholder questions
Approach
- Close with what you would do differently, concretely.
- Name the disagreement or constraint, and how you resolved it with evidence.
- Pick a story where you drove the decision, not one where you observed it.
Follow-up
- What would you do differently if you ran that project again?
- What did you decide not to do, and why?
Defend a null result against a programme sponsor
Medium · regression to the mean · difference-in-differences · stakeholder management
A care management programme enrolled the top 1 percent of members by prior-year allowed spend. The sponsor's deck shows allowed PMPM for enrollees falling 34 percent from the year before enrollment to the year after, and asks for budget to triple the programme. You rebuild the evaluation with a concurrent comparison group selected by the identical spend rule in the same period. The difference-in-differences estimate is a 3 percent reduction with a confidence interval spanning zero. Deliverable: how you present this, to whom, in what order, and what you propose next.
Approach
- Name the probe: whether you can deliver a finding that costs somebody their programme without softening it into uselessness or creating an adversary who routes around you next time.
- Lead with the mechanism, not the verdict. Show the comparison group's own unadjusted drop, which will be large, because a cohort selected on an extreme of the outcome regresses toward the mean whether or not anyone intervenes. The sponsor's 34 percent is mostly that, and it is a property of the selection rule rather than a criticism of their clinicians.
- Give the sponsor the finding privately before it appears in any deck their leadership sees. Being surprised in a room is what turns a methods disagreement into a political one.
- State the estimate with its interval and say what it rules out as well as what it fails to establish. A 3 percent point estimate whose interval crosses zero is not evidence of no effect; it is insufficient power to separate a modest effect from none, and those are different claims.
- Arrive with a design rather than only an objection. Propose a regression discontinuity at the enrollment threshold if the rule is applied sharply, or a randomised rollout across the next wave of eligible members, and state the sample size needed to detect the effect size the sponsor believes in.
Follow-up
- The sponsor says withholding the programme from a comparison group is unethical. What do you propose instead?
- Leadership wants one number for the board next week. What do you give them?
- What result would change your mind and make you believe the 34 percent?
Own an analysis that shipped wrong and was acted on
Easy · retrospective · ownership · data quality
Describe an analysis you delivered that was wrong, where someone acted on it before the error surfaced. Pick something with a mechanism you can name, not a typo. Cover what the number claimed, what was actually true, how much time passed before it was caught, who caught it, and what you told the people who had already acted. Deliverable: a five-minute account that ends with the specific control you added afterwards, plus one occasion since when that control has fired.
Approach
- Read the probe: the interviewer is testing whether you detect your own errors and whether the correction was structural. Pick an error with a nameable mechanism (a denominator built from distinct members instead of member-months, a series read before claims runout completed, a cohort selected on the outcome) so the story has a diagnosis rather than a mood.
- Open with the decision that was made on your number, not with the bug. The severity of an analytic error is measured in the action it caused: a rate filing, a staffing plan, a programme expansion.
- State the counterfactual number. 'The true figure was 14.1 admissions per 1,000 member-years, not 9.8' is a fact; 'it was off by a lot' is not.
- Describe the detection path honestly, including whether you found it or somebody else did. Say how long it took, because time to detection is the part you actually control next time.
- Close on the control, and make it something that protects a reader who has never met you: a unit test on the denominator, a paid-through date stamped on every chart, a required exclusions block in the spec template. Name one later date it caught something.
Follow-up
- What would have had to be true for you to catch this before delivery rather than after?
- Did the stakeholder change how much they trust your work, and did you want them to?
- Give an example of a control you added that turned out to be the wrong control.