Cloud Cost by Team

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
City and County of San Francisco

Problem

Credits land in cost_allocs as negative amounts, and they count against a team's spend. For the budget review, an analyst needs each team's total cost allocation, from highest to lowest.

Spend by team. Who's burning most?

Tables

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 5 of 16 rows
team_nametotal_cost
platform180855.7
DATA-ENG179212.3
Platform177568.9
data-eng175178.1
mobile166250.72

Worked solution and explanation

This is one collapse of cost_allocs into a net total per team_name, dressed up as a budget review. Anyone writes SUM(amount). The grain is what separates candidates: the labels come in casing variants ('platform' and 'Platform', 'data-eng' and 'DATA-ENG'), and the expected output keeps each spelling as its own row. Reach for LOWER(team_name) to tidy them and you get 14 rows instead of 16, two totals inflated by the merge, a reshuffled top of the list, and a failed grade.

Getting to the query

Step 1: Settle the grain before writing anything

One output row per team_name value as stored. The preview settles it: 'platform' and 'Platform' each carry their own total, so the grouping key is the raw column with nothing wrapped around it.

Step 2: Sum every row, credits included

SUM(amount) nets the one negative row (a -120.5 credit on 'backend') against that team's spend. A WHERE amount > 0 guard looks careful and silently overstates backend.

Step 3: Sort on the alias, not the expression

ORDER BY total_cost DESC sorts on the aggregate you already named, so the sum is written once. The order is graded, so the sort is part of the answer, not presentation.

Net spend per team label, largest first
SELECT team_name, SUM(amount) AS total_cost
FROM cost_allocs
GROUP BY team_name
ORDER BY total_cost DESC
Tidied labels
GROUP BY LOWER(team_name) folds 'Platform' into 'platform' and 'DATA-ENG' into 'data-eng': 14 rows, two totals near 358k and 354k that exist nowhere in the expected output.
Labels as stored
GROUP BY team_name returns 16 rows, every spelling with its own total, exactly the shape the preview shows.

Common follow-up questions