Echo Chamber

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
Amazon

Problem

List the top 20 pairs of different calls in api_calls that returned the same HTTP method and the same status code, each pair identified by its two call IDs. A reliability reviewer hunting duplicated responses reads them highest status first, and within a status by the lower call ID and then the higher one.

Same status, same pattern. Coincidence?

Tables

api_calls

Columns: call_id INTEGER, endpoint TEXT, method TEXT, status INTEGER, latency REAL, user_id INTEGER, call_time TEXT, err_msg TEXT

api_calls: 10 of 670 rows
call_idendpointmethodstatuslatencyuser_idcall_timeerr_msg
8079/api/v1/ordersPOST2004.21002026-02-02 01:07:00NULL
8158/api/v2/productsPUT2007.91972026-03-03 02:14:00NULL
8237/api/v1/searchDELETE20111.62942026-04-04 03:21:00NULL
8316/api/v1/auth/loginPATCH20415.33912026-05-05 04:28:00NULL
8395/api/v1/auth/logoutget30119NULL2026-06-06 05:35:00NULL
8474/api/v2/analyticspost40022.75852026-07-07 06:42:00Not found
8553/api/v1/paymentsGET40126.46822026-08-08 07:49:00Unauthorized
8632/api/v1/users/POST40330.17792026-09-09 08:56:00Rate limit exceeded
8711/api/v2/products/PUT40433.88762026-01-10 09:03:00Internal server error
8790/api/v1/usersDELETE50037.5NULL2026-02-11 10:10:00Bad gateway

Expected output

First 5 of 20 rows
call_id_1call_id_2methodstatus
894816492get503
997517025PATCH503
886916451PATCH502
989616984DELETE502
879016410DELETE500

Worked solution and explanation

What this is really testing

This is a self-join that forms unique unordered pairs, wearing a duplicate-detection costume. The skill being probed: can you take one table and match each row against other rows that share a key (method and status here) without pairing a row with itself and without listing the same pair twice? Anyone can write FROM api_calls a JOIN api_calls b ON a.method = b.method AND a.status = b.status. The trick is the a.call_id < b.call_id predicate. Drop it and every call pairs with itself and every real pair shows up in both orderings, so your top 20 becomes duplicated noise.


The one predicate that matters

Equality on method and status gives you the candidate pairs, but it also gives you (x, x) and both (x, y) and (y, x). The single character that fixes both problems is the strict inequality on call_id. Because < is strict, a call can never match itself; because it is directional, exactly one of the two mirror orderings survives. That is what makes each real pair land on the list once.

Equality only
ON a.method = b.method AND a.status = b.status. Ten matching calls in a group produce 100 rows: 10 self-pairs plus every real pair counted twice. LIMIT 20 fills up with garbage before you reach a distinct pair.
Add `a.call_id < b.call_id`
Same join plus a.call_id < b.call_id. The same group of ten produces 45 rows, one per genuine unordered pair. Self-pairs are gone and no mirror duplicates remain, so the top 20 is 20 real pairs.

Building it

Step 1: Join the table to itself on the shared key

Alias api_calls twice, as a and b, and match on a.method = b.method AND a.status = b.status. Every combination of two calls that agree on both columns becomes a candidate row.

Step 2: Kill self-pairs and mirror duplicates

Add a.call_id < b.call_id. This does two jobs at once: it excludes a.call_id = b.call_id so no call pairs with itself, and it keeps only one of (x, y) / (y, x) so each unordered pair appears exactly once, smaller ID first.

Step 3: Order totally, then cap

Sort by status descending, then by call_id_1 and call_id_2, and LIMIT 20. The call ID keys are not cosmetic: status 500 alone holds 17 pairs on this data and only six slots remain after the 503s and 502s, so without them any six of those pairs would satisfy the order and the cut would be arbitrary.


The solution

Self-join with an inequality to form unique pairs
SELECT a.call_id AS call_id_1, b.call_id AS call_id_2, a.method, a.status
FROM api_calls a
JOIN api_calls b
  ON a.method = b.method
 AND a.status = b.status
 AND a.call_id < b.call_id
ORDER BY a.status DESC, call_id_1, call_id_2
LIMIT 20

Common follow-up questions