The Company You Keep

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
Asked in
Walmart

Problem

Count the Friday sessions in user_sessions as an integer tally per date, earliest date first, for the users the experimentation team is tracking. Those are the users who share an experiment in experiments with at least one other user.

Only experiments with a crowd count. Find the Friday sessions they drove.

Tables

user_sessions

Columns: session_id INTEGER, user_id INTEGER, device_id INTEGER, session_start TEXT, session_duration_sec INTEGER, pages_viewed INTEGER

user_sessions: 10 of 200 rows
session_iduser_iddevice_idsession_startsession_duration_secpages_viewed
70611972302026-02-02 01:00:00533
71222942592026-03-03 02:00:00766
71833912882026-04-04 03:00:00999
72444883172026-05-05 04:00:0012212
73055853462026-06-06 05:00:0014515
73666823752026-07-07 06:00:0016818
74277794042026-08-08 07:00:0019121
7488876NULL2026-09-09 08:00:0021424
75499734622026-01-10 09:00:0023727
761010704912026-02-11 10:00:0026030

experiments

Columns: exp_id INTEGER, exp_name TEXT, variant TEXT, user_id INTEGER, outcome REAL, created TEXT, platform TEXT

experiments: 10 of 200 rows
exp_idexp_namevariantuser_idoutcomecreatedplatform
1053checkout_v3variant_a10011.32026-02-02android
1106onboard_flowvariant_b19722.62026-03-03web
1159pricing_tiervariant_c29433.92026-04-04iOS
1212search_rankholdout39145.22026-05-05Android
1265rec_model_bcontrol48856.52026-06-06NULL
1318notif_freqvariant_a585NULL2026-07-07WEB
1371home_layoutvariant_b68279.12026-08-08NULL
1424new_feed_algovariant_c77990.42026-09-09ios
1477checkout_v3holdout8761.72026-01-10android
1530onboard_flowcontrol973132026-02-11web

Expected output

First 5 of 25 rows
session_datetotal_sessions
2023-01-131
2023-05-051
2023-09-011
2025-11-072
2026-07-242

Worked solution and explanation

What this is really testing

Beneath the Friday framing this is a semi-join: does this session's user belong to any experiment that a second user also joined? The metric lives at session grain, one row per session, but the co-enrollment test lives at experiment grain. The trap is letting those two grains collide. If you join experiments straight onto user_sessions and COUNT(*), one Friday session gets counted once for every peer in every experiment its user touched, and the total balloons into numbers no reader could predict. The move that saves you is to collapse co-enrollment down to a set of qualifying users first, then count each session exactly once.


Build it in layers

Step 1: Find the experiments with a crowd

Self-join experiments to itself on exp_name with e1.user_id <> e2.user_id. An exp_name survives only if two different users share it. Wrap it in SELECT DISTINCT exp_name so a popular experiment does not repeat downstream.

Step 2: Collapse co-enrollment to a set of users

Join those experiments back to experiments and take DISTINCT user_id. This is the step that protects the count: every co-enrolled user now appears exactly once, so the later join to sessions is one to one and cannot fan out.

Step 3: Filter Fridays and count sessions

In SQLite strftime('%w', session_start) returns a text weekday, 0 for Sunday through 6 for Saturday, so CAST to INTEGER and compare to 5 for Friday. Join the qualifying users to their sessions, group by date(session_start), COUNT(*), and order chronologically.


The solution

FRIDAY SESSIONS FOR CO-ENROLLED USERS
WITH shared_experiments AS (
  SELECT DISTINCT e1.exp_name
  FROM experiments e1
  INNER JOIN experiments e2
    ON e1.exp_name = e2.exp_name
   AND e1.user_id <> e2.user_id
),
co_enrolled_users AS (
  SELECT DISTINCT e.user_id
  FROM experiments e
  INNER JOIN shared_experiments s
    ON e.exp_name = s.exp_name
)
SELECT date(us.session_start) AS session_date,
       COUNT(*) AS total_sessions
FROM user_sessions us
INNER JOIN co_enrolled_users cu
  ON us.user_id = cu.user_id
WHERE CAST(strftime('%w', us.session_start) AS INTEGER) = 5
GROUP BY date(us.session_start)
ORDER BY session_date
Join then COUNT(*)
experiments fans out onto every matching session, so COUNT(*) counts join rows and one session becomes many. The answer inflates and swings with how many peers each experiment has.
Semi-join on distinct users
co-enrollment collapses to one row per user, the session join stays one to one, and COUNT(*) counts sessions. The answer is the real Friday session tally.

COMMON FOLLOW-UP QUESTIONS

Common follow-up questions