Alert Severity

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
L5

Problem

Offsets are showing up twice in topic after topic of stream_msgs, and the on-call engineer wants each message lined up against the one just before it in its topic, in offset order. For every message that has an earlier one in its topic, show its offset, the prior offset, how many different offsets the topic has reached so far, the message's position in the topic, and the fraction of messages up to that point that carried a new offset.

When the alarms go off, who screams loudest?

Tables

stream_msgs

Columns: msg_id INTEGER, topic TEXT, part_key TEXT, payload TEXT, offset INTEGER, produced TEXT, consumer TEXT

stream_msgs: 10 of 200 rows
msg_idtopicpart_keypayloadoffsetproducedconsumer
10079order-updateskey-3{"event": "type_1", "ts": 1700003600, "data": {"id": 1}}1002026-02-02 01:07:13search-indexer
10158page-viewskey-6{"event": "type_2", "ts": 1700007200, "data": {"id": 2}}2002026-03-03 02:14:26ml-pipeline
10237click-streamkey-9{"event": "type_3", "ts": 1700010800, "data": {"id": 3}}3002026-04-04 03:21:39reporting-svc
10316payment-eventskey-12{"event": "type_4", "ts": 1700014400, "data": {"id": 4}}4002026-05-05 04:28:52NULL
10395inventory-synckey-15{"event": "type_5", "ts": 1700018000, "data": {"id": 5}}5002026-06-06 05:35:05notification-svc
10474audit-logkey-18{"event": "type_6", "ts": 1700021600, "data": {"id": 6}}6002026-07-07 06:42:18NULL
10553metric-ingestNULL{"event": "type_7", "ts": 1700025200, "data": {"id": 7}}7002026-08-08 07:49:31data-warehouse
10632Una Bennettkey-24{"event": "type_8", "ts": 1700028800, "data": {"id": 8}}8002026-09-09 08:56:44NULL
10711Van Woodkey-27{"event": "type_9", "ts": 1700032400, "data": {"id": 9}}9002026-01-10 09:03:57fraud-detector
10790Wes Barneskey-30{"event": "type_0", "ts": 1700036000, "data": {"id": 10}}10002026-02-11 10:10:10analytics-svc

Expected output

First 5 of 160 rows
topicoffsetprev_offsetmsg_rankmsg_row_numnew_offset_share
Ada Jenkins14001400120.5
Ada Jenkins54001400230.6666666666666666
Ada Jenkins54005400240.5
Ada Jenkins94005400350.6
Bob Perry15001500120.5

Worked solution and explanation

What this really is

This is a duplicate-delivery audit dressed up as offset bookkeeping. Every offset in stream_msgs lands twice in its topic, so the real question is whether you can keep two different counts apart over one ordering: the unique offsets a topic has reached (DENSE_RANK()) and the messages it has delivered (ROW_NUMBER()). Anyone can write the three window calls. What separates candidates is the last column: msg_rank / msg_row_num is integer over integer, and on this seed it truncates to 0 on every one of the 160 rows. The quieter failure is removing each topic's first message too early, which renumbers everything after it.

Walk it

Step 1: Order each topic by offset

offset is an integer, so PARTITION BY topic ORDER BY offset already sorts numerically. All three window functions share that one spec, so the engine sorts each topic once and derives three columns from the same pass.

Step 2: Keep the unique count and the position apart

The two '5400' rows in 'Ada Jenkins' tie on the order key. DENSE_RANK() gives both a 2 (two unique offsets reached), while ROW_NUMBER() gives them 3 and 4 (third and fourth message delivered). The gap between the two counts is exactly the replays the on-call engineer is chasing.

Step 3: Filter after the windows run

prev_offset is NULL only on each topic's first message, and a WHERE cannot test a window result computed in the same SELECT. Compute the windows in a derived table and drop prev_offset IS NULL outside it, so the surviving rows keep the positions they earned. That is why the preview starts at msg_row_num 2.

Step 4: Make the share fractional

msg_rank and msg_row_num are both integers, and integer division floors: 2 / 3 is 0. CAST(msg_rank AS REAL) turns the numerator into a float, so the same division returns 0.667.

The solution

One window spec, filter outside, cast before dividing
SELECT
  topic,
  offset,
  prev_offset,
  msg_rank,
  msg_row_num,
  CAST(msg_rank AS REAL) / msg_row_num AS new_offset_share
FROM (
  SELECT
    topic,
    offset,
    LAG(offset) OVER (PARTITION BY topic ORDER BY offset) AS prev_offset,
    DENSE_RANK() OVER (PARTITION BY topic ORDER BY offset) AS msg_rank,
    ROW_NUMBER() OVER (PARTITION BY topic ORDER BY offset) AS msg_row_num
  FROM stream_msgs
) AS positioned
WHERE prev_offset IS NOT NULL
Integer over integer
msg_rank / msg_row_num returns 0 on all 160 rows. Past each topic's first message, the unique offsets reached are always fewer than the messages delivered, so every quotient sits below 1 and floors away.
Cast first
CAST(msg_rank AS REAL) / msg_row_num returns 0.5, 0.667, 0.5, 0.6 down 'Ada Jenkins': the share of messages so far that actually brought a new offset.

Common follow-up questions