Three Lowest Distinct Cloud Cost Amounts

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
Revolut

Problem

Every row of cloud_costs is one billed line item, and a line item recorded with no amount carries no cost to compare. Return the three lowest unique cost amounts on the bill, smallest first.

The three cheapest bills on record.

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

Expected output

First 3 of 3 rows
amount
-268.5
-224.8
-181.1

Worked solution and explanation

What this is really asking

This is a distinct-values selection dressed up as a billing audit. Anyone can sort cloud_costs by amount and keep three rows. The data decides who passes. Every charge on this bill is stored on two line items, and a dozen line items carry no amount at all. Sort raw rows and -268.5 takes two of the three slots. Trust the default ascending sort and the first slot goes to a blank. Either way the third credit, -181.1, never makes the list.

Step 1: Project only amount

The question is about values, not line items. Leave cost_id or svc_name in the select list and two line items with the same amount stop being duplicates.

Step 2: Collapse repeats with DISTINCT

SELECT DISTINCT amount turns each repeated charge into one row, so the three slots go to three different amounts.

Step 3: Push missing amounts past the numbers

A line item with a NULL amount has no cost to compare, yet SQLite and Spark sort NULL first in ascending order. NULLS LAST keeps it out of the three. A WHERE amount IS NOT NULL filter returns the same rows.

Step 4: Sort ascending, then cut at three

ORDER BY amount ASC puts the credits (negative amounts) first, which is right: a credit is the cheapest line on a bill. LIMIT 3 applies after both the dedup and the sort.

The solution

Dedup, sort with blanks last, take three
SELECT DISTINCT amount
FROM cloud_costs
ORDER BY amount ASC NULLS LAST
LIMIT 3
Dedup only
SELECT DISTINCT amount
FROM cloud_costs
ORDER BY amount ASC
LIMIT 3

Opens with a blank row: the missing amount sorts ahead of every credit, so -181.1 is pushed out.

No dedup
ORDER BY amount ASC NULLS LAST LIMIT 3 without DISTINCT returns -268.5, -268.5, -224.8: three rows, two values.
Dedup, blanks last
SELECT DISTINCT amount ... NULLS LAST LIMIT 3 returns -268.5, -224.8, -181.1: three rows, three values.

Follow-up questions

Common follow-up questions