The Weight of the Cloud

A medium SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.

Domain
SQL
Difficulty
medium
Seniority
L4
Asked in
Apple

Problem

The 2026 close takes only bills dated in 2026, and since those books in cloud_costs run only through September there are three calendar quarters to fill. Finance weights each of those bills by every allocation in cost_allocs booked against the same service, whatever period the allocation fell in; report each quarter's total weighted spend as a decimal number at full precision, with no rounding.

Not every dollar counts the same. Close the quarter.

Tables

cloud_costs

Columns: cost_id INTEGER, provider TEXT, svc_name TEXT, region TEXT, amount REAL, acct_id TEXT, bill_date TEXT

cloud_costs: 10 of 200 rows
cost_idprovidersvc_nameregionamountacct_idbill_date
543GCPS3us-west-219.33acct-10012026-02-01
586AzureRDSeu-west-137.16acct-10022026-03-01
629awsLambdaap-southeast-154.99acct-10032026-04-01
672gcpBigQueryus-central172.82acct-10042026-05-01
715AWSCloud Runeurope-west190.65acct-10052026-06-01
758GCPBlob Storageus-east-1108.48acct-10062026-07-01
801AzureCosmos DBus-west-2126.31acct-10072026-08-01
844awsCloudFronteu-west-1144.14acct-10082026-09-01
887gcpPub/Subap-southeast-1161.97NULL2026-01-01
930AWSEC2us-central1179.8acct-10102026-02-01

cost_allocs

Columns: alloc_id INTEGER, team_name TEXT, svc_name TEXT, region TEXT, amount REAL, period TEXT, acct_id TEXT, category TEXT

cost_allocs: 10 of 200 rows
alloc_idteam_namesvc_nameregionamountperiodacct_idcategory
129data-engS3us-west-283.212026-02acct-101storage
158ml-teamRDSeu-west-1156.422026-03acct-102network
187frontendLambdaap-south-1229.632026-04acct-103database
216backendBigQueryus-central1-120.52026-05acct-104ml
245devopsCloudFronteurope-west1376.052026-06acct-105other
274securityEKSap-southeast-1449.262026-07acct-106compute
303mobileSQSeu-central-1522.472026-08acct-107storage
332PlatformEC2us-east-1595.682026-09NULLnetwork
361DATA-ENGS3us-west-2668.892026-01acct-109database
390platformRDSeu-west-1742.12026-02acct-110ml

Expected output

First 3 of 3 rows
quarterweighted_spend
Q14311722773.2458
Q23148557719.7053
Q34319401574.6013

Worked solution and explanation

What this really is

Strip the finance language away and this is a weighted rollup with three quiet ways to go wrong. Each cost has to carry the full allocation total of its service, each bill has to land in the right calendar quarter, and only this year's bills count. Anyone can write the join. What separates candidates is keeping every allocation (match on svc_name alone, never tidied with region or acct_id), fencing the year on the bill side, and remembering that bill_date is TEXT, so its month must become a number before BETWEEN can bucket it. Get the match wrong and the quarters come out billions low; skip the fence and older bills inflate every quarter and conjure a fourth; skip the cast and every bill piles into one bucket. None of these throws an error.


Walking the query

Step 1: Match costs to their allocations on svc_name

Match cloud_costs to cost_allocs on svc_name and nothing else. S3 has two allocation rows, so every S3 cost appears twice, once per allocation. That duplication is the weighting, not a bug to squash.

Step 2: Fence the costs to 2026

cloud_costs spans several years. Keep strftime('%Y', cc.bill_date) = '2026' on the cost side so no other year's bills land in these buckets. The allocation period is a booking month, not a bill date; filtering it too drops valid pairs.

Step 3: Cast the month, then bucket it

strftime('%m', ...) hands back '04', not 4. Without the CAST(... AS INTEGER), the string never satisfies BETWEEN 4 AND 6 and every row slides into the ELSE. January to March is Q1, April to June is Q2, and since the 2026 books are open only through September, everything after June is Q3.

Step 4: Weight and total

SUM(cc.amount * ca.amount) per quarter. Because the match already fanned out, this equals each cost times the sum of every allocation booked against its service. Report it unrounded, as finance asked.


The solution

Bucketed weighted spend per quarter
SELECT
    CASE
        WHEN CAST(strftime('%m', cc.bill_date) AS INTEGER) BETWEEN 1 AND 3 THEN 'Q1'
        WHEN CAST(strftime('%m', cc.bill_date) AS INTEGER) BETWEEN 4 AND 6 THEN 'Q2'
        ELSE 'Q3'
    END AS quarter,
    SUM(cc.amount * ca.amount) AS weighted_spend
FROM cloud_costs cc
JOIN cost_allocs ca
  ON cc.svc_name = ca.svc_name
WHERE strftime('%Y', cc.bill_date) = '2026'
GROUP BY quarter
Naive: tidy the match
A DISTINCT or a pick-one-allocation subquery keeps a single allocation per service, or an extra cc.region = ca.region predicate trims the pairs. Either way S3's second allocation never touches the weight and the totals come out low.
Correct: keep every allocation
Join on svc_name alone and SUM(cc.amount * ca.amount) over the fanned-out rows, or pre-sum ca.amount per service and multiply once. Each cost is weighted by the full sum of its service's allocations.

Common follow-up questions