Coding questions · CVS Health
Aggregate radiology spend and derive fiscal month
This question evaluates a candidate's competency in data manipulation and preprocessing using SQL/Python, covering robust dtype specification, null handling, numeric aggregation and percentage computation, datetime parsing, and fiscal-month derivation.
Using Python/pandas, complete the tasks below. Assume the following CSV-like input, where service_dt is object dtype and amounts may be negative (adjustments). Treat missing paid_amt as 0 when aggregating, but do not create NaNs during type conversion.
radiology.csv (toy data)
claim_id,procedure_group,service_dt,paid_amt
1001,CT,2020-07-01 13:05:00,120.00
1002,MRI,2020-10-15 09:30:00,250.00
1003,CT,2020-10-20 11:00:00,-20.00
1004,XRay,2020-12-05 08:00:00,80.00
1005,MRI,2020-01-02 14:10:00,
Tasks
- Load the file robustly (explicit dtypes, parse_dates) and aggregate paid_amt by procedure_group to produce columns: procedure_group, paid_amt_sum (rounded to 2 decimals).
- Add each group's percentage of total paid_amt as pct_of_total (0–100 with two decimals). Ensure total uses post-cleaning values and is not double-counted.
- Convert service_dt from object to datetime and add an integer fiscal_month column where fiscal year starts on October 1 (Oct=1, Nov=2, …, Sep=12). Validate on the sample rows so that 2020-10-15 maps to fiscal_month=2. Show the resulting dtypes and demonstrate that the transformation is vectorized (no per-row Python loops). Handle bad or missing dates gracefully (coerce to NaT, then impute fiscal_month with 0 for unknown).
Aggregate paid amounts by procedure group
You are given a table of radiology claims. The paid_amt column can contain negative values (adjustments), and some paid_amt values may be missing (NULL). Treat missing paid_amt as 0 when aggregating, and include negative values in the arithmetic sum.
Write a SQL query to aggregate paid_amt by procedure_group and return one row per procedure_group with the following columns:
- procedure_group
- paid_amt_sum: the sum of paid_amt for that procedure_group, treating NULL as 0, rounded to 2 decimal places.
Do not filter out any procedure_group values. The result can be returned in any row order.
Table radiology_claims
| column | type | constraints |
|---|---|---|
| claim_id | INT | PRIMARY KEY, NOT NULL |
| procedure_group | VARCHAR(20) | NOT NULL |
| service_dt | VARCHAR(19) | |
| paid_amt | DECIMAL(10,2) |
Sample data:
| claim_id | paid_amt | procedure_group | service_dt |
|---|---|---|---|
| 1001 | 120 | CT | 2020-07-01 13:05:00 |
| 1002 | 250 | MRI | 2020-10-15 09:30:00 |
| 1003 | -20 | CT | 2020-10-20 11:00:00 |
| 1004 | 80 | XRay | 2020-12-05 08:00:00 |
| 1005 | NULL | MRI | 2020-01-02 14:10:00 |
Expected output
One row per procedure_group with the sum of paid_amt (NULL treated as 0) rounded to 2 decimal places. Using the sample data, CT has 120 + (-20) = 100, MRI has 250 + 0 = 250, and XRay has 80.
| paid_amt_sum | procedure_group |
|---|---|
| 100 | CT |
| 250 | MRI |
| 80 | XRay |
Hints
- Use COALESCE (or a similar function) to treat NULL paid_amt as 0 before summing.
- Apply ROUND(..., 2) to the aggregated sum, not to individual rows.
Add percentage of total paid amount per procedure group
Using the same radiology_claims table, extend the previous aggregation.
Compute, for each procedure_group:
- paid_amt_sum: the sum of paid_amt (treating NULL as 0), rounded to 2 decimals.
- pct_of_total: that group’s percentage share of the overall paid_amt total, on a 0–100 scale, rounded to 2 decimals.
The overall total must be calculated from the same cleaned paid_amt values (NULL treated as 0) and must not be double-counted. Return one row per procedure_group with columns:
- procedure_group
- paid_amt_sum
- pct_of_total
The result can be returned in any row order.
Table radiology_claims
| column | type | constraints |
|---|---|---|
| claim_id | INT | PRIMARY KEY, NOT NULL |
| procedure_group | VARCHAR(20) | NOT NULL |
| service_dt | VARCHAR(19) | |
| paid_amt | DECIMAL(10,2) |
Sample data:
| claim_id | paid_amt | procedure_group | service_dt |
|---|---|---|---|
| 1001 | 120 | CT | 2020-07-01 13:05:00 |
| 1002 | 250 | MRI | 2020-10-15 09:30:00 |
| 1003 | -20 | CT | 2020-10-20 11:00:00 |
| 1004 | 80 | XRay | 2020-12-05 08:00:00 |
| 1005 | NULL | MRI | 2020-01-02 14:10:00 |
Expected output
One row per procedure_group with its sum of paid_amt and that sum as a percentage of the total sum across all groups. Using the sample data, group sums are: CT=100, MRI=250, XRay=80; total=430. Percentages rounded to 2 decimals: CT≈23.26, MRI≈58.14, XRay≈18.60.
| paid_amt_sum | pct_of_total | procedure_group |
|---|---|---|
| 100 | 23.26 | CT |
| 250 | 58.14 | MRI |
| 80 | 18.6 | XRay |
Hints
- First compute per-group sums in a CTE or subquery, then compute the overall total in a separate step.
- Use a CROSS JOIN (or scalar subquery) to make the total available to each group when calculating pct_of_total.
Derive fiscal month from service date with October fiscal year start
Derive a fiscal month from a string service date (fiscal year starts in October)
You are given a single table, radiology_claims, where the service_dt column stores the service date and time as a string (e.g. '2020-10-15 09:30:00'). Some rows may have a service_dt that is NULL or that is not a valid YYYY-MM-DD HH:MI:SS timestamp.
Write one PostgreSQL query that, for every row in radiology_claims, returns:
service_ts—service_dtsafely parsed into atimestamp. Ifservice_dtisNULLor cannot be parsed as a validYYYY-MM-DD HH:MI:SSvalue,service_tsmust beNULL(the query must not error on a bad string).fiscal_month— an integer giving the fiscal month under a fiscal year that starts on October 1:- October = 1, November = 2, December = 3, January = 4, ..., September = 12.
- When
service_tsisNULL(unknown / invalid date), setfiscal_month = 0.
Required output columns (in this order)
claim_idprocedure_groupservice_dt(the original string)service_ts(parsed timestamp, orNULL)fiscal_month(integer)
Sorting
Return one row per claim, ordered by claim_id ascending.
Note: the original problem assumed a SQL-Server
TRY_CONVERT/MONTH(...)dialect. This is graded on PostgreSQL, so use a regex guard plusto_timestamp(...)for the safe parse andEXTRACT(MONTH FROM ...)for the month.
Table radiology_claims
| column | type | constraints |
|---|---|---|
| claim_id | INT | PRIMARY KEY, NOT NULL |
| procedure_group | VARCHAR(20) | NOT NULL |
| service_dt | VARCHAR(19) | |
| paid_amt | DECIMAL(10,2) |
Sample data:
| claim_id | paid_amt | procedure_group | service_dt |
|---|---|---|---|
| 1001 | 120 | CT | 2020-07-01 13:05:00 |
| 1002 | 250 | MRI | 2020-10-15 09:30:00 |
| 1003 | -20 | CT | 2020-10-20 11:00:00 |
| 1004 | 80 | XRay | 2020-12-05 08:00:00 |
| 1005 | NULL | MRI | 2020-01-02 14:10:00 |
| 1006 | 60 | XRay | not-a-date |
| 1007 | 45 | CT | NULL |
Expected output
One row per claim with the original string service_dt, the safely parsed service_ts (NULL when invalid/missing), and the integer fiscal_month under an October-start fiscal year (NULL date -> 0); ordered by claim_id.
| claim_id | fiscal_month | procedure_group | service_dt | service_ts |
|---|---|---|---|---|
| 1001 | 10 | CT | 2020-07-01 13:05:00 | 2020-07-01T13:05:00+00:00 |
| 1002 | 1 | MRI | 2020-10-15 09:30:00 | 2020-10-15T09:30:00+00:00 |
| 1003 | 1 | CT | 2020-10-20 11:00:00 | 2020-10-20T11:00:00+00:00 |
| 1004 | 3 | XRay | 2020-12-05 08:00:00 | 2020-12-05T08:00:00+00:00 |
| 1005 | 4 | MRI | 2020-01-02 14:10:00 | 2020-01-02T14:10:00+00:00 |
| 1006 | 0 | XRay | not-a-date | NULL |
| 1007 | 0 | CT | NULL | NULL |
Hints
- PostgreSQL has no TRY_CAST that yields NULL on failure — guard the conversion with a regex (
service_dt ~ '^[0-9]{4}-...$') and only then callto_timestamp(service_dt, 'YYYY-MM-DD HH24:MI:SS'); otherwise produce NULL. - Use
EXTRACT(MONTH FROM service_ts)for the calendar month, then a CASE: months >= 10 subtract 9, months <= 9 add 3. - Check
service_ts IS NULLfirst in the outer CASE so invalid/missing dates yield fiscal_month = 0.