Cost Efficiency Ratio
An easy SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.
- Domain
- SQL
- Difficulty
- easy
- Seniority
- L3
- Asked in
- Forbes
Problem
Our chargeback sheet quotes each cloud service's average charge per billing line in whole dollars, and the figures we recompute by hand from cloud_costs keep landing a dollar high on some services. Rebuild that number for every service, counting only the lines that actually charged something.
Dollars in, value out. What's the ratio?
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 |
Expected output
| svc_name | avg_charge_dollars |
|---|---|
| BigQuery | 875 |
| Blob Storage | 861 |
| Cloud Run | 803 |
| CloudFront | 976 |
| Cosmos DB | 918 |
Worked solution and explanation
What this really is
This is a per-service average dressed up as a chargeback reconciliation, and the whole problem is in the symptom. Anyone can write SUM(amount) / COUNT(*) per svc_name. What separates candidates is reading 'a dollar high' correctly: the sheet drops the cents, so the hand checks were rounding. Round and RDS reads 840 where the sheet says 839, and EC2 reads 944 instead of 943. Forget which lines count and it gets worse: credits and lines with no amount drag EC2 all the way down to 660.
Build it in three decisions
Step 1: Keep only lines that charged something
WHERE amount > 0 removes credits (negative amount) and lines where amount is NULL in one predicate, because a comparison with NULL is never true. This matters because COUNT(*) counts every row it is handed: EC2 has three lines with no amount, and leaving them in divides its spend by 10 lines instead of 7.
Step 2: Average per service
Group by svc_name and divide SUM(amount) by COUNT(*). Once the filter has run, COUNT(*) and COUNT(amount) agree, so this is the same number as an average of amount; writing the ratio keeps the denominator, 'billing lines', visible to whoever audits it.
Step 3: Drop the cents
CAST(... AS INTEGER) truncates toward zero. Every average here is positive, so truncation is the floor, which is what the sheet does: 839.51 becomes 839.
SELECT
svc_name,
CAST(SUM(amount) / COUNT(*) AS INTEGER) AS avg_charge_dollars
FROM cloud_costs
WHERE amount > 0
GROUP BY svc_name- Rounded (the hand check)
- RDS 839.51 becomes 840, Cloud Run 803.85 becomes 804, EC2 943.94 becomes 944. Six of ten services land a dollar high, and only the ones whose cents are 50 or more.
- Cents dropped (the sheet)
CAST(... AS INTEGER)gives 839, 803 and 943. Services with small cents, like CloudFront at 996.02, agree either way, which is why the mismatch looked random.
Common follow-up questions
- Finance now wants credits netted against spend but still divided only by charged lines. What changes? (Moves the credit rows from the filter into the numerator: a conditional sum, not a WHERE.)
- How would you show the dropped cents so the sheet can be audited? (Return the raw ratio next to the truncated one and reason about which one feeds downstream totals.)
- What if `amount` were stored as integer cents instead? (Now `SUM(amount_cents) / COUNT(*)` is integer division, and the truncation happens whether you wanted it or not.)