Top of the Bill
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
- L3
- Asked in
- Slickdeals
Problem
Finance is reviewing the cloud bills and wants to see which services dominate the spend. Among the services that also appear in the cost allocations, list the two with the highest total cloud cost, the biggest spender first.
Every cloud bill has a headliner or two. Find them.
Tables
cloud_costs
Columns: cost_id INTEGER, provider TEXT, svc_name TEXT, region TEXT, amount REAL, acct_id TEXT, bill_date TEXT
| cost_id | provider | svc_name | region | amount | acct_id | bill_date |
|---|---|---|---|---|---|---|
| 543 | GCP | S3 | us-west-2 | 19.33 | acct-1001 | 2026-02-01 |
| 586 | Azure | RDS | eu-west-1 | 37.16 | acct-1002 | 2026-03-01 |
| 629 | aws | Lambda | ap-southeast-1 | 54.99 | acct-1003 | 2026-04-01 |
| 672 | gcp | BigQuery | us-central1 | 72.82 | acct-1004 | 2026-05-01 |
| 715 | AWS | Cloud Run | europe-west1 | 90.65 | acct-1005 | 2026-06-01 |
| 758 | GCP | Blob Storage | us-east-1 | 108.48 | acct-1006 | 2026-07-01 |
| 801 | Azure | Cosmos DB | us-west-2 | 126.31 | acct-1007 | 2026-08-01 |
| 844 | aws | CloudFront | eu-west-1 | 144.14 | acct-1008 | 2026-09-01 |
| 887 | gcp | Pub/Sub | ap-southeast-1 | 161.97 | NULL | 2026-01-01 |
| 930 | AWS | EC2 | us-central1 | 179.8 | acct-1010 | 2026-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
| alloc_id | team_name | svc_name | region | amount | period | acct_id | category |
|---|---|---|---|---|---|---|---|
| 129 | data-eng | S3 | us-west-2 | 83.21 | 2026-02 | acct-101 | storage |
| 158 | ml-team | RDS | eu-west-1 | 156.42 | 2026-03 | acct-102 | network |
| 187 | frontend | Lambda | ap-south-1 | 229.63 | 2026-04 | acct-103 | database |
| 216 | backend | BigQuery | us-central1 | -120.5 | 2026-05 | acct-104 | ml |
| 245 | devops | CloudFront | europe-west1 | 376.05 | 2026-06 | acct-105 | other |
| 274 | security | EKS | ap-southeast-1 | 449.26 | 2026-07 | acct-106 | compute |
| 303 | mobile | SQS | eu-central-1 | 522.47 | 2026-08 | acct-107 | storage |
| 332 | Platform | EC2 | us-east-1 | 595.68 | 2026-09 | NULL | network |
| 361 | DATA-ENG | S3 | us-west-2 | 668.89 | 2026-01 | acct-109 | database |
| 390 | platform | RDS | eu-west-1 | 742.1 | 2026-02 | acct-110 | ml |
Expected output
| svc_name | total_amount |
|---|---|
| BigQuery | 17503.4 |
| CloudFront | 17296.920000000002 |
Worked solution and explanation
What this really is
Underneath the FinOps framing this is a semi-join feeding a top-N. The real question the interviewer is probing: can you express 'services that also have allocations on file' as a membership test, not a row-multiplying join? Reach for a plain INNER JOIN on svc_name and every service with many allocation rows gets its cloud cost summed once per allocation, so the totals balloon and the top two you report is not the top two finance sees. cost_allocs is a filter here, never a source of dollars: the moment you SUM across the join, or add its amounts in, the numbers stop tying out.
Reading the requirements
Step 1: Restrict to allocated services without fanning out
The requirement is membership, not a join: cc.svc_name IN (SELECT svc_name FROM cost_allocs). This keeps each cloud_costs row exactly once. An INNER JOIN would duplicate a cost row once per matching allocation and inflate SUM(cc.amount).
Step 2: Aggregate and take the two heaviest
SUM(cc.amount) GROUP BY cc.svc_name gives per-service spend, then ORDER BY total_amount DESC LIMIT 2 takes the two heaviest. Sum cc.amount only; cost_allocs is a filter, never a metric source.
The solution
SELECT cc.svc_name,
SUM(cc.amount) AS total_amount
FROM cloud_costs cc
WHERE cc.svc_name IN (SELECT svc_name FROM cost_allocs)
GROUP BY cc.svc_name
ORDER BY total_amount DESC
LIMIT 2;- Wrong (join fans out)
- INNER JOIN
cost_allocsca ONcc.svc_name=ca.svc_nameduplicates each cost row once per matching allocation, so SUM(cc.amount) is multiplied by the allocation count per service. - Right (semi-join)
cc.svc_nameIN (SELECTsvc_nameFROMcost_allocs) is a membership test: each cost row survives exactly once and the sum stays honest.
Common follow-up questions
Common follow-up questions
- Rewrite it so that a tie for second place surfaces every tied service. (Forces the `DENSE_RANK` refactor and tests whether you understand LIMIT's tie behavior.)
- How would you confirm `cost_allocs` does not inflate the per-service totals? (Probes join-cardinality discipline: a COUNT(*) versus COUNT(DISTINCT `svc_name`) sanity check on `cost_allocs`.)
- What if finance only wants a single billing year's spend? How would you add that window? (Adds a date predicate on `bill_date` and tests keeping it sargable so partition pruning fires on the 15M-row table.)
- How would you show each service's allocated budget alongside its actual cloud cost? (Tests joining back to `cost_allocs` after aggregation without reintroducing fan-out.)