As a Data Scientist at S&P Global Energy, you sit at the intersection of complex energy market dynamics and advanced analytical modeling. Your work is fundamental to providing the actionable intelligence that powers global commodity markets, energy transition strategies, and risk management frameworks. By transforming vast, high-velocity datasets into predictive models and clear insights, you enable stakeholders to navigate the volatility of the energy sector with precision.
You will contribute to high-impact projects that range from building factor models for market performance to optimizing supply-chain data pipelines. Whether you are working on time-series forecasting, NLP-driven sentiment analysis of energy reports, or developing robust machine learning pipelines, your output directly influences the decisions of industry leaders. This role requires a unique blend of technical rigor and domain curiosity, as you must not only build accurate models but also communicate their business implications to non-technical stakeholders.
The interview process at S&P Global Energy is highly dependent on the specific team's project focus; expect deep dives into the technical stack you have listed on your resume.
Recruiter Screen
reportedWhoever runs this call is usually not a practitioner. They take notes, and a hiring manager skims those notes later, so the real question is whether your work survives being written down by someone outside the field. Test every project sentence against that: could a non-specialist repeat it correctly without knowing what a propensity score is? Carry a plain-language version of each project and one reason you want this particular role that you could not copy onto another application. Vagueness at this stage reads as inexperience, even when the underlying work was genuinely deep.
What to demonstrate
- Whether a non-specialist can restate your projects accurately, since their paraphrase is what reaches the hiring manager
- Whether your reason for wanting the role points at the work itself rather than the company's reputation
- Whether your language signals the level being screened for: what you decided yourself versus what you were handed
How to prepare
- Write a two-sentence, jargon-free version of each major project: the question nobody could answer, and the decision your work changed. Read it to someone outside data and have them repeat it back
- Point your 'why this role' answer at something concrete in the job description or the product surface you would be working on, and keep it to two sentences
- Have two questions ready about measurement: which metric the team is held to, and who acts on an analysis once it lands
Technical Assessments
reportedMuch 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
Final Interviews
reportedWhere a loop ends with a senior leader, that conversation is rarely another skills test. The technical signal already exists by then, so the questions tend to open up: what you would look at first, where a metric you have heard about could mislead, what you would push back on. The decision being made is scope, which in practice means level and how much you would be trusted to own unsupervised. Treating it as a formality is the usual mistake. An open question late in the day is still being scored, and a vague answer reads as someone who has not run anything themselves.
What to demonstrate
- Whether your view of the business has anything specific behind it, given that you are working only from what is public and are expected to say so
- Whether the scope of work you describe owning matches the scope of the role, instead of sitting a level below it
- Whether you can disagree with something concrete and stay useful about it, rather than agreeing with everything said in the room
- Whether your questions are ones only this person could answer, as opposed to ones the recruiter already covered
How to prepare
- Build one view you could defend for two minutes using only public information: what the funnel probably looks like, which metric likely drives decisions, and where that metric could mislead. Being wrong for a stated reason survives this round; having no view does not
- Write down the largest piece of work you have owned from question to decision, who else touched it, and what you decided alone, then check that it reads at the level you are interviewing for
- Prepare one thing you would want changed if you joined and phrase it as a question rather than a verdict, so it opens a conversation instead of closing one
PracHub editorial advice for the preparation topics above.
Scoring intermittent demand with MAPE
MAPE is undefined whenever the actual is zero, which is most days for a C-class item at a forward-stocking location, and it is asymmetric even where it is defined: under-forecasting is bounded at 100 percent error while over-forecasting is unbounded. Optimising it therefore drives systematic under-forecasting on exactly the items whose stockouts are most expensive, and the bias is invisible in the headline because the zero-actual rows were dropped before averaging. Use WMAPE (sum of absolute errors over sum of actuals), a scaled error such as RMSSE, or a pinball loss at the service quantile the policy targets, and always state the aggregation level and forecast lag, because the same series scores very differently at daily SKU-store level and weekly SKU-region level.
Computing average inventory from period-end snapshots
Shipments cluster before period close, so the month-end on-hand position is systematically the lowest point of the month; turns computed against it are biased high and days of supply biased low, frequently by ten to twenty percent, and the bias grows precisely when close-period push is strongest. The same shape of error appears when a daily snapshot is joined to shipment events on date equality: a SKU with several legs on one day fans the snapshot out and multiplies the valued inventory. Average across every daily snapshot in the window for the denominator, and join snapshots to events with an explicit as-of condition and a row-count check at each grain before aggregating.
Sizing estimates built on unnamed, unrevisable assumptions
Write each assumption as a named number you can change, then show the arithmetic so the interviewer can challenge one input instead of the whole answer. Finish by saying which assumption the result is most sensitive to, which matters more than the point estimate.
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.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
How do you ensure your machine learning models are scalable and produc…
How do you ensure your machine learning models are scalable and production-ready?
Approach
- Check what information would not exist at prediction time, and exclude it.
- 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.
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?
Given a dataset, how would you approach building a time-series model t…
Given a dataset, how would you approach building a time-series model to predict commodity price trends?
Approach
- Say how the offline result would be validated online before it is trusted.
- Set a baseline first, so any model has something honest to beat.
- Check what information would not exist at prediction time, and exclude it.
Follow-up
- Where could label leakage enter this setup?
- How would you choose the decision threshold, and who owns that choice?
How would you design a factor model to backtest the performance of an …
How would you design a factor model to backtest the performance of an energy-related asset?
Approach
- Frame the prediction: the label, the moment of prediction, and the action it triggers.
- Say how the offline result would be validated online before it is trusted.
- Set a baseline first, so any model has something honest to beat.
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?
As-of join snapshots to order lines without merge_asof
You have fct_order_line (order_line_id, sku_id, ship_from_location_id, actual_ship_at_utc, shipped_qty, shipment_id) and fct_inventory_daily (inventory_date, sku_id, location_id, available_qty). For every shipped line, attach available_qty from the latest snapshot strictly before the ship date for that exact sku and node, plus the shipment's delivery timestamp from fct_shipment_leg (leg_id, shipment_id, delivered_at_utc, leg_status). The output must have exactly one row per input order line. pandas.merge_asof is not available; implement the as-of match yourself.
Approach
- Collapse fct_shipment_leg to one row per shipment_id before joining anything. A shipment is one or more legs, so a direct line-to-leg join multiplies every line by its leg count and quietly inflates every sum computed afterwards.
- Define the shipment-level delivery as the maximum delivered_at_utc across its legs, and set it null if any leg is not delivered, since the customer has the order only when the last leg lands.
- Sort the snapshot frame by (sku_id, location_id, inventory_date) and the line frame by the same key plus ship date, then use np.searchsorted with side='left' on the sorted dates within each key group to find the insertion point; the matching snapshot is the row at position minus one.
- Guard the boundary explicitly: an insertion point of 0 means no snapshot exists before that ship date, and the result must be null rather than the first available future snapshot. Count those lines and report them.
- Assert the output row count equals the input line count immediately after each merge, before any aggregation. Row-count drift is the only symptom a silent fan-out produces, and it is invisible once the frame has been grouped.
Worked solution 30 min
- Aggregate legs by shipment_id to produce delivered_at_utc as the max, leg_count, and a delivered_all flag from leg_status.
- Left join that one-row-per-shipment frame onto fct_order_line by shipment_id and assert the row count is unchanged.
- Sort snapshots and lines by the composite key, then compute per-group insertion points with np.searchsorted and subtract one.
- Mask positions below zero to null, take available_qty at the remaining positions, and attach it as available_qty_prior.
- Validate on a single sku-location pair by printing its snapshot dates and one line's ship date and confirming the chosen date by eye.
Follow-up
- The snapshot is taken at the node's local end of day and actual_ship_at_utc is UTC. Where does that break the strictly-before rule and what do you need from dim_location to fix it?
- How would you extend this to allocate each leg's linehaul cost back to the order lines it carried?
- What changes if a line ships in two partial shipments?
Can you walk me through your process for optimizing a Python script fo…
Can you walk me through your process for optimizing a Python script for performance?
Approach
- 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.
- Handle the rows that do not match: a LEFT JOIN with a NULL check is usually the question.
Follow-up
- What breaks if events arrive late or out of order?
- How would you verify this result without re-running the same query?
Weekly unit fill rate by ship-from node
fct_order_line holds one row per customer order line per ship-from node in its terminal state, with ordered_qty, shipped_qty, requested_ship_date, actual_ship_at_utc, line_status and ship_from_location_id; dim_location carries location_code. Produce weekly first-pass unit fill rate by node. Numerator is shipped_qty on lines shipped on or before requested_ship_date; denominator is ordered_qty on every line requested that week except line_status = 'cancelled_by_customer'. Return node, week, numerator, denominator and rate, plus one network total row. State in the output how substituted lines are counted.
Approach
- Anchor the query at order-line grain filtered on requested_ship_date, never at shipments: a line that was never filled has no shipment row, and starting from shipments deletes exactly the failures the metric exists to count.
- Build the numerator as a conditional SUM over the same row set, SUM(CASE WHEN actual_ship_at_utc IS NOT NULL AND its ship date <= requested_ship_date THEN shipped_qty ELSE 0 END), so short and backordered lines stay in the denominator instead of vanishing behind a WHERE clause.
- Exclude only line_status = 'cancelled_by_customer'. A line cancelled for lack of supply is a service failure and belongs in the denominator at full ordered_qty.
- Group by node and by DATE_TRUNC('week', requested_ship_date), then build the network row by re-summing numerator and denominator across nodes, not by averaging the node rates.
- Declare the substitution rule explicitly in one column or one comment: lines with substituted_sku_id NOT NULL count toward the numerator only if substitution is an accepted fill in the service definition.
Worked solution 20 min
- Filter fct_order_line to requested_ship_date inside the window and line_status <> 'cancelled_by_customer'; count the rows removed by that filter and keep the count.
- Compute num = SUM(CASE WHEN actual_ship_at_utc::date <= requested_ship_date THEN shipped_qty ELSE 0 END) and den = SUM(ordered_qty) in the same SELECT.
- GROUP BY ship_from_location_id, DATE_TRUNC('week', requested_ship_date) and join dim_location for location_code.
- Add the network row from a second aggregate over the same base set: SUM(num) / SUM(den).
- Report the excluded-line count and the substitution rule beside the rate so the number is auditable.
Follow-up
- actual_ship_at_utc is UTC but requested_ship_date is a local calendar date at the node. How does the comparison change for a node at UTC+9, and which direction does the error run?
- Fill rate rose two points while a node's short_reason_code mix moved from 'no_stock' toward 'credit_hold'. Is that a supply improvement?
- How would you hold SKU mix fixed so the network number is comparable month over month?
What are the common challenges you face when working with unstructured…
What are the common challenges you face when working with unstructured data, such as market reports or news sentiment?
Approach
- Restate the decision this analysis has to support, and who acts on the answer.
- Name one primary metric, then the guardrail that stops it being gamed.
- Fix the population and the time window before naming any metric.
Follow-up
- What would you do if the primary metric and the guardrail moved in opposite directions?
- How would you detect that the metric is being gamed rather than genuinely improving?
Describe a project where you had to translate a complex business probl…
Describe a project where you had to translate a complex business problem into a data science solution.
Approach
- Name one primary metric, then the guardrail that stops it being gamed.
- State what result would change your recommendation, so the answer is falsifiable.
- Decompose the metric into the rates that drive it, and say which one you would check first.
Follow-up
- What would you do if the primary metric and the guardrail moved in opposite directions?
- How would you detect that the metric is being gamed rather than genuinely improving?
Design a switchback for a pick-path change in one facility
A new pick-path and slotting rule can only run facility-wide: pickers, aisles and outbound loads are shared, so no order-level split is possible, and only one regional DC will pilot it. The metric is units picked per labour hour by shift. Shift-level SD is 6% of the mean and the team wants to detect 3%. You have twelve weeks, two shifts a day, six days a week. Specify the randomisation, the block length, the analysis unit, and how you handle carryover between blocks.
Approach
- Say why parallel assignment fails here: every candidate unit (order, wave, picker) draws on the same aisles and the same slotting state, so a treated order's pick time depends on how many other orders are treated. That is interference, and it biases any within-facility parallel comparison toward zero.
- Randomise time instead of units. One shift is one block, assigned by a coin flip within each day so that the two shifts of a day take opposite arms; that balances day of week and demand level by construction and gives 144 blocks, 72 per arm.
- Handle carryover explicitly, because slotting state persists across a shift boundary. Exclude a fixed burn-in at the start of each block from the metric window and pre-register its length. If the change requires a physical re-slot that cannot be reversed between shifts, a switchback is impossible and the design has to become a pre/post against a comparison facility with all the weakness that implies.
- Analyse at the block grain: mean units per labour hour per shift, regressed on treatment with day fixed effects. Take p-values from randomisation inference over the realised assignment mechanism rather than from iid OLS errors, since consecutive shifts are autocorrelated and blocks are few.
- Check the power before committing: MDE = 2.80 * 0.06 * sqrt(1/72 + 1/72) = 2.8% relative, just inside the 3% target, so there is no slack for cancelled shifts and the protocol must say what happens when blocks are lost.
Worked solution 30 min
- Enumerate the blocks: 12 weeks x 6 days x 2 shifts = 144, randomised within day so each day contributes one treated and one control shift.
- Define the metric window inside each block with a fixed burn-in excluded, and lock both before the first block runs.
- Compute the MDE: 2.80 * 0.06 * sqrt(2/72) = 2.80 * 0.06 / 6 = 0.028, or 2.8% relative.
- Estimate the effect on block-level means with day fixed effects, then permute the within-day coin flips 10,000 times to get the p-value under the design.
- Report the effect with the burn-in exclusion stated, plus a sensitivity run at a longer burn-in.
Follow-up
- Volume is 40% higher on Mondays and the rule's benefit scales with congestion. What does that do to the estimand, and how would you change the design?
- The re-slot takes four hours and cannot be reversed between shifts. What design would you run instead, and what do you lose?
Unit fill rate fell four points in one region
Weekly unit fill rate for one region fell from 96.1 percent to 92.0 percent over four weeks and has not recovered. Network fill rate is flat. You have fct_order_line (ordered_qty, shipped_qty, requested_ship_date, ship_from_location_id, sku_id, line_status, short_reason_code), dim_location (location_type, region_code, echelon) and dim_sku (abc_class, xyz_class, lifecycle_status). Produce the first four query cuts, say what each one rules in or out, and name the single most likely cause together with the evidence that would confirm it. Thirty minutes, SQL plus a short written argument.
Approach
- Rebuild the metric by summing shipped_qty and ordered_qty to region level and dividing once, rather than averaging per-SKU-location rates. An unweighted mean of cell rates moves with portfolio mix on its own, so if the drop does not survive re-summing there is nothing physical to diagnose.
- Cut by ship_from_location_id first. If one node carries the whole drop the mix of demand across nodes is not the story and the problem is local; if every node fell a little, the cause sits upstream in supply or forecast rather than in any warehouse.
- Decompose the region change over abc_class by xyz_class cells into within-cell, mix and interaction terms: delta R = SUM(w0 * (r1 - r0)) + SUM(r0 * (w1 - w0)) + SUM((w1 - w0) * (r1 - r0)), where w is a cell's share of the denominator and r is its rate. A dominant mix term means demand moved toward hard-to-serve intermittent items and no cell actually got worse.
- Group the lost units (ordered_qty minus shipped_qty) by short_reason_code. 'no_stock' points at planning, 'pick_shortage' and 'damage_on_pick' mean the stock was physically present and execution lost it, 'allocation_rule' means the units existed and were promised to someone else, and 'credit_hold' is not a supply chain failure at all.
- Only then cross the weekly series against the promotion calendar, against SKUs with lifecycle_status = 'pre_launch' cutting in, and against accounts placing their first order in the window. A step change starting in the same week as a promotion or a new-item onboarding is a demand-side event, not a degradation.
Follow-up
- Fill rate is flat nationally but down in this region. What does that tell you about where the stock went, and how would you test it?
- Most of the failed units carry short_reason_code = 'no_stock', yet on_hand_qty at the node stayed above reorder_point_qty all month. How is that possible?
- Would you publish this rate weighted by units or by revenue, and which team gets a different answer from each?
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.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Build 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.
Practice prompt ↗Practice prompt ↗Worked solution ↗02Joins, 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.
Practice prompt ↗Practice prompt ↗03Window 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.
Practice prompt ↗Practice prompt ↗04The 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.
Practice prompt ↗Practice prompt ↗Worked solution ↗05Write 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.
Practice prompt ↗Practice prompt ↗06One 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.
Practice prompt ↗Practice prompt ↗07Full 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.
Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
Data people depend on systems owned by other teams, and much of the job is negotiating for instrumentation, access, or a fix to a broken pipeline. Prepare an example of getting something changed upstream that you did not control. Describe what you asked for, what you traded, and how you worked while you waited.
How do you handle missing or noisy data in a large-scale energy datase…
How do you handle missing or noisy data in a large-scale energy dataset?
Approach
- Name the disagreement or constraint, and how you resolved it with evidence.
- State the situation in two sentences and spend the rest on your reasoning.
- 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?
Tell me about a time you had to explain a technical model to a non-tec…
Tell me about a time you had to explain a technical model to a non-technical stakeholder.
Approach
- Quantify the outcome, including what you would not claim credit for.
- State the situation in two sentences and spend the rest on your reasoning.
- Name the disagreement or constraint, and how you resolved it with evidence.
Follow-up
- What did you decide not to do, and why?
- How did you know the outcome was caused by your change?
Disagree with a planning manager about a safety stock cut
A planning product manager proposes cutting safety stock 30 percent on every C and Z class sku-location cell, citing a MAPE improvement from 41 to 28 percent over two quarters. Checking the query, you find MAPE is computed over fct_inventory_daily rows where the actual is greater than zero, and the actual used is shipped_qty rather than demand_qty; stockout_flag is true on 14 percent of the rows that were kept. You have fifteen minutes in his planning review. Make the disagreement, and propose what you would do instead of the flat cut.
Approach
- Lead with the decision at risk, not the metric error: a 30 percent cut on intermittent items is the cheapest way to convert a measurement artefact into stockouts eight weeks later, by which time nobody will connect the two.
- Name the two defects precisely. Dropping zero-actual rows is not a rounding choice, it removes most of the history for a C-class item at a forward-stocking location and it removes the rows where over-forecasting is penalised, so the surviving MAPE is biased toward whichever series stocked out. Using shipped_qty as the actual scores the forecast against a supply ceiling, so a series looks more accurate the more often it ran out.
- Offer the replacement metric in the same breath: WMAPE, sum of absolute errors over sum of actuals against demand_qty, computed at the sku-location-week grain the ordering decision uses and at the lag it uses, reported next to signed bias so a persistently short series cannot hide inside an accuracy number.
- Propose the smaller action that is defensible now: recompute on the corrected basis, rank cells by bias rather than accuracy, and cut cover only where the corrected series is unbiased or over-forecasting, in a staged rollout with a service guardrail.
- Give him the win he actually wants: if the corrected numbers still support cuts on a subset, say so in advance, so the disagreement is about evidence rather than about territory.
Follow-up
- He says demand_qty is itself incomplete because customers stop ordering what shows out of stock. Is he right, and what do you do about it?
- Which items would you leave alone regardless of what the corrected metric says?
- 01
How do you handle missing or noisy data in a large-scale energy dataset?
- 02
Tell me about a time you had to explain a technical model to a non-technical stakeholder.
- 03
A planning product manager proposes cutting safety stock 30 percent on every C and Z class sku-location cell, citing a MAPE improvement from 41 to 28 percent over two quarters. Checking the query, you find MAPE is computed over fct_inventory_daily rows where the actual is greater than zero, and the actual used is shipped_qty rather than demand_qty; stockout_flag is true on 14 percent of the rows that were kept. You have fifteen minutes in his planning review. Make the disagreement, and propose what you would do instead of the flat cut.
Is this an official S&P Global Energy interview guide?
No. It is PracHub's own research and practice material for the Data Scientist role at S&P Global Energy. Rounds and questions reflect what candidates have reported, not a process S&P Global Energy has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗How much time should I spend preparing for the coding portion?
Prioritize medium-level coding challenges and focus on writing clean, readable code rather than just obscure algorithms. Since many technical rounds are verbal or whiteboard-based, focus on talking through your logic clearly.
PracHub interview research ↗Is there a specific focus on ML vs. Data Engineering?
It depends on the team, but most roles require a hybrid mindset. You should be comfortable with both the mathematical foundations of ML and the practical engineering skills needed to move data from A to B.
PracHub interview research ↗What is the best way to stand out during the "project deep dive"?
Be honest about the limitations of your work. The best candidates can articulate what went wrong in a project, why it happened, and how they would do it differently today.
PracHub interview research ↗Sources & methodology 3 sources ↗
No official company page is cited. Rounds and questions come from candidate reports and PracHub editorial material; each source shows the date it was read.
- 01PracHub interview research ↗
PracHub editorial research into this company and role, maintained with this guide. Candidate-reported, not an employer publication.
PracHub page · Accessed 2026-09-22 - 02PracHub Data Scientist practice ↗
Cross-company practice questions for this role.
PracHub page · Accessed 2026-09-22 - 03PracHub interview preparation framework ↗
The framework the preparation plan follows.
PracHub page · Accessed 2026-09-22