cswork / libraryOpen practice workspace

Coding questions · Capital One

Design a reproducible data pipeline for modeling

This question evaluates a candidate's ability to design reproducible, idempotent data pipelines and feature engineering workflows using SQL and Python, including handling late or out-of-order events, deduplication, backfills, data-quality checks, and orchestration.

You receive raw clickstream events and a user table. Build a reproducible daily pipeline that outputs user-day features for modeling. It must be idempotent, handle late-arriving/out-of-order events, include quality checks and unit tests, and support backfills.

Schema and small samples:

users
user_id | signup_date | country
u1 | 2025-05-20 | US
u2 | 2025-06-02 | CA
u3 | 2025-06-15 | US
events
event_id | user_id | ts | event_type | amount_usd | source
e1 | u1 | 2025-06-01T12:00:00Z | page_view | null | ads
e2 | u1 | 2025-06-01T12:10:00Z | add_to_cart | null | ads
e3 | u1 | 2025-06-01T12:45:00Z | purchase | 30.0 | ads
e4 | u2 | 2025-06-02T00:05:00Z | page_view | null | seo
e5 | u2 | 2025-06-02T00:40:00Z | purchase | 20.0 | seo

Tasks:

  1. In SQL or Python, define transformations to produce user-day features: sessions (30-min inactivity gap), total_page_views, add_to_cart_count, purchases_count, revenue_usd, days_since_signup, country, and top_source for the day; dedupe by event_id; ensure UTC→date bucketing is correct.
  2. Describe how you guarantee idempotency and correctness with late/out-of-order data (e.g., watermarking, upserts/merge, partition overwrite vs. append-only with versioning).
  3. Specify a backfill plan for 2025-06-01 to 2025-08-31, including how you would re-run only affected partitions safely.
  4. Propose concrete data-quality checks (row-count reconciliations, not-null/valid-set for event_type, nonnegative revenue) and two unit tests that would have caught common bugs.
  5. Outline orchestration (DAG tasks and dependencies), storage formats/partitioning, and how you would expose the output for both training and online inference.

Build daily user features with sessions from clickstream events

You are given two tables, users and events, with raw clickstream data. For each user and calendar day on which they generated at least one event, produce a single row of user-day features.

Definitions and requirements:

  • A "day" is based on the UTC timestamp ts, using the calendar date of ts.
  • A "session" is a contiguous sequence of events for a user on a given day where the gap between consecutive events is at most 30 minutes. A new session starts if the previous event is more than 30 minutes earlier or does not exist (first event of the day).
  • If duplicate rows exist for the same event_id, they should be de-duplicated so that each event_id contributes at most once.
  • For each user_id and day, output the following columns:
    • user_id
    • event_date (the UTC calendar date of ts)
    • country (from the users table)
    • sessions (number of sessions that day)
    • total_page_views (number of events with event_type = 'page_view')
    • add_to_cart_count (number of events with event_type = 'add_to_cart')
    • purchases_count (number of events with event_type = 'purchase')
    • revenue_usd (sum of amount_usd for purchase events on that day; treat null as 0)
    • days_since_signup (event_date minus signup_date, in whole days)
    • top_source (the source value with the highest number of events for that user and day; if there is a tie, pick the lexicographically smallest source)

Write a single SQL query that produces this user-day feature table from the schemas and sample data below.

Table users

columntypeconstraints
user_idVARCHAR(10)PRIMARY KEY
signup_dateDATENOT NULL
countryVARCHAR(2)NOT NULL

Sample data:

countrysignup_dateuser_id
US2025-05-20u1
CA2025-06-02u2
US2025-06-15u3

Table events

columntypeconstraints
event_idVARCHAR(10)PRIMARY KEY
user_idVARCHAR(10)NOT NULL
tsTIMESTAMPNOT NULL
event_typeVARCHAR(50)NOT NULL
amount_usdDECIMAL(10,2)
sourceVARCHAR(20)NOT NULL

Sample data:

amount_usdevent_idevent_typesourcetsuser_id
NULLe1page_viewads2025-06-01T12:00:00u1
NULLe2add_to_cartads2025-06-01T12:10:00u1
30e3purchaseads2025-06-01T12:45:00u1
NULLe4page_viewseo2025-06-02T00:05:00u2
20e5purchaseseo2025-06-02T00:40:00u2

Expected output

One row per (user_id, event_date) with daily session counts, per-event-type counts, revenue, days since signup, country, and top_source for that day, for users that have at least one event on that date.

add_to_cart_countcountrydays_since_signupevent_datepurchases_countrevenue_usdsessionstop_sourcetotal_page_viewsuser_id
1US122025-06-011302ads1u1
0CA02025-06-021202seo1u2

Hints

  1. Start by de-duplicating events on event_id using ROW_NUMBER() over PARTITION BY event_id.
  2. Use window functions (LAG) to detect 30-minute gaps for session boundaries, and conditional aggregation (FILTER or CASE) to compute per-event-type counts.