Bookends of the Week

A hard SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.

Domain
SQL
Difficulty
hard
Seniority
L4
Asked in
Meta

Problem

Find what percentage of each week's spending in transactions landed on Monday and what percentage landed on Sunday, with each week identified by its week-of-year number. Report both shares as integer percentage points with any fraction dropped rather than rounded, so a 37.9% share reads 37.

Every week has two edges. Weigh what lands on each.

Tables

transactions

Columns: transaction_id INTEGER, user_id INTEGER, product_id INTEGER, quantity INTEGER, total_amount REAL, transaction_date TEXT

transactions: 10 of 200 rows
transaction_iduser_idproduct_idquantitytotal_amounttransaction_date
10671971001223.462026-02-02
11342941050336.932026-03-03
12013911099450.42026-04-04
12684881148563.872026-05-05
13355851197002026-06-06
14026821246290.812026-07-07
146977912953104.282026-08-08
153687613444117.752026-09-09
160397313935-452026-01-10
1670107014421144.692026-02-11

Expected output

First 5 of 50 rows
week_nummonday_pctsunday_pct
000100
0104
02012
03130
043211

Worked solution and explanation

What this is really asking

Beneath the calendar language this is a share-of-total done twice against one denominator. For each week you need Monday's slice and Sunday's slice of the same weekly pie. The trap is filtering to Monday and Sunday first: the week total then holds only those two days, both shares inflate until they sum to about 100, and the numbers look tidy and mean nothing. The fix is folding both numerators and the full-week denominator into one grouped pass. The quieter tell is the last step: whole points with the fraction dropped is a type change, and reaching for ROUND turns 37.9 into 38.


Break down the requirements

Step 1: Read the date twice

strftime('%W', transaction_date) gives the week bucket ('00' to '53', Monday-start), and strftime('%w', transaction_date) gives the day of week as text where Sunday is '0' and Monday is '1'. Comparing against those two codes is enough.

Step 2: One grouped pass, three sums

Group by week_num. Inside that group SUM(total_amount) is the denominator, and two conditional sums, SUM(CASE WHEN ... = '1' ...) and SUM(CASE WHEN ... = '0' ...), are the Monday and Sunday numerators. The ELSE 0 keeps a week with no Monday at 0 instead of dropping it.

Step 3: Scale, then cast to INTEGER

Divide monday_total * 100.0 by week_total, then CAST(... AS INTEGER). The cast is the requirement: it drops the fraction toward zero and hands back an integer, exactly what 'whole points, not rounded' asks for.


The solution

Monday and Sunday share per week
WITH weekly AS (
  SELECT
    strftime('%W', transaction_date) AS week_num,
    SUM(total_amount) AS week_total,
    SUM(CASE WHEN strftime('%w', transaction_date) = '1' THEN total_amount ELSE 0 END) AS monday_total,
    SUM(CASE WHEN strftime('%w', transaction_date) = '0' THEN total_amount ELSE 0 END) AS sunday_total
  FROM transactions
  GROUP BY week_num
)
SELECT
  week_num,
  CAST(monday_total * 100.0 / week_total AS INTEGER) AS monday_pct,
  CAST(sunday_total * 100.0 / week_total AS INTEGER) AS sunday_pct
FROM weekly;
Round it
ROUND(monday_total * 100.0 / week_total) returns 38.0 for a 37.9 share: the wrong number, and still a decimal.
Cast it
CAST(monday_total * 100.0 / week_total AS INTEGER) returns 37: the fraction is dropped and the type is an integer, both of which the grade checks.

Common follow-up questions

Common follow-up questions