Coding questions · Meta
Compute multi-account user distribution and unread pct
This question evaluates a data scientist's ability to perform relational data manipulation and aggregation with SQL or Python, covering competencies such as handling one-to-many joins, grouping and bucketing counts, deduplicating across related tables, and computing cohort-level percentages from boolean flags.
You are working on a product where a user can have multiple accounts, and each account can receive notifications.
Tables
Assume the following schemas:
users
user_idBIGINT PRIMARY KEYcreated_atTIMESTAMP
accounts
account_idBIGINT PRIMARY KEYuser_idBIGINT NOT NULL REFERENCESusers(user_id)created_atTIMESTAMP
notifications
notification_idBIGINT PRIMARY KEYaccount_idBIGINT NOT NULL REFERENCESaccounts(account_id)created_atTIMESTAMPis_readBOOLEAN --FALSEmeans unread
Tasks
-
Account-count distribution: Return the number of users who have:
- exactly 2 accounts
- exactly 3 accounts
- 4 or more accounts
Required output columns:
account_bucket,num_users. -
Unread-notification rate among multi-account users: Among users with 2+ accounts, compute the percentage of users who have at least one unread notification across any of their accounts.
Required output columns:
pct_users_with_unread(as a percent or decimal; specify which you choose).
Multi-account user distribution (2, 3, 4+ accounts)
You are given a list of user accounts in the accounts table (each row is one account belonging to a user). Write a SQL query to return the number of users who have exactly 2 accounts, exactly 3 accounts, and 4 or more accounts.
Output columns:
accounts_bucket: one of ('2', '3', '4+')user_count: number of users in that bucket
Notes:
- Users with 0 or 1 account should not appear in the output.
- Count users based on the number of rows in
accountsperuser_id.
Table users
| column | type | constraints |
|---|---|---|
| user_id | INT | PRIMARY KEY |
| user_name | VARCHAR(50) | NOT NULL |
| created_at | DATE | NOT NULL |
Sample data:
| created_at | user_id | user_name |
|---|---|---|
| 2025-01-05 | 1 | Ava |
| 2025-01-06 | 2 | Ben |
| 2025-01-07 | 3 | Cleo |
| 2025-01-08 | 4 | Dev |
| 2025-01-09 | 5 | Eli |
| 2025-01-10 | 6 | Fay |
| 2025-01-11 | 7 | Gus |
| 2025-01-12 | 8 | Hana |
Table accounts
| column | type | constraints |
|---|---|---|
| account_id | INT | PRIMARY KEY |
| user_id | INT | NOT NULL |
| created_at | DATE | NOT NULL |
| last_visit_at | DATE |
Sample data:
| account_id | created_at | last_visit_at | user_id |
|---|---|---|---|
| 101 | 2025-02-01 | 2025-05-30 | 1 |
| 201 | 2025-02-02 | 2025-05-28 | 2 |
| 202 | 2025-02-15 | 2025-05-31 | 2 |
| 301 | 2025-02-03 | 2025-05-20 | 3 |
| 302 | 2025-03-01 | 2025-05-29 | 3 |
| 303 | 2025-03-20 | NULL | 3 |
| 401 | 2025-02-04 | 2025-05-01 | 4 |
| 402 | 2025-02-18 | 2025-05-15 | 4 |
| 403 | 2025-03-05 | 2025-05-21 | 4 |
| 404 | 2025-03-25 | 2025-05-31 | 4 |
| 501 | 2025-02-05 | 2025-04-30 | 5 |
| 502 | 2025-02-19 | 2025-05-10 | 5 |
| 503 | 2025-03-06 | 2025-05-11 | 5 |
| 504 | 2025-03-26 | 2025-05-12 | 5 |
| 505 | 2025-04-10 | 2025-05-13 | 5 |
| 601 | 2025-02-06 | 2025-05-05 | 6 |
| 602 | 2025-04-01 | 2025-05-25 | 6 |
| 801 | 2025-02-07 | 2025-05-22 | 8 |
| 802 | 2025-02-20 | 2025-05-23 | 8 |
| 803 | 2025-03-07 | 2025-05-24 | 8 |
| 804 | 2025-04-02 | 2025-05-25 | 8 |
Table notifications
| column | type | constraints |
|---|---|---|
| notification_id | INT | PRIMARY KEY |
| account_id | INT | |
| created_at | TIMESTAMP | NOT NULL |
| read_at | TIMESTAMP | |
| notification_type | VARCHAR(30) | NOT NULL |
Sample data:
| account_id | created_at | notification_id | notification_type | read_at |
|---|---|---|---|---|
| 201 | 2025-05-20 09:00:00 | 1 | promo | 2025-05-20 10:00:00 |
| 202 | 2025-05-31 08:00:00 | 2 | security | NULL |
| 301 | 2025-05-10 12:00:00 | 3 | system | 2025-05-10 12:05:00 |
| 302 | 2025-05-29 15:00:00 | 4 | promo | 2025-05-29 16:00:00 |
| 303 | 2025-05-30 11:00:00 | 5 | promo | 2025-05-30 11:10:00 |
| 505 | 2025-05-13 09:30:00 | 6 | system | NULL |
| 601 | 2025-05-01 07:00:00 | 7 | promo | 2025-05-01 07:05:00 |
| 602 | 2025-05-25 18:00:00 | 8 | security | 2025-05-26 08:00:00 |
| 804 | 2025-05-25 10:00:00 | 9 | promo | NULL |
| NULL | 2025-05-28 10:00:00 | 10 | system | NULL |
Expected output
Three rows: counts of users with exactly 2 accounts, exactly 3 accounts, and 4 or more accounts.
| accounts_bucket | user_count |
|---|---|
| 2 | 2 |
| 3 | 1 |
| 4+ | 3 |
Hints
- First aggregate
accountsbyuser_idto get an account count per user. - Use a CASE expression to bucket counts into 2 / 3 / 4+.
Percent of multi-account users with unread notifications
A user can have multiple accounts (accounts table). Notifications belong to accounts (notifications.account_id). A notification is considered unread when read_at IS NULL.
Write a SQL query to compute, among users with 2 or more accounts, what percentage of users have at least one unread notification across any of their accounts.
Output columns:
total_multi_account_usersusers_with_unreadpct_with_unread(as a percentage from 0 to 100, rounded to 2 decimals)
Notes:
- Users with multiple accounts but zero notifications should be counted in the denominator.
- Ignore notifications whose
account_idis NULL or does not match any account.
Table users
| column | type | constraints |
|---|---|---|
| user_id | INT | PRIMARY KEY |
| user_name | VARCHAR(50) | NOT NULL |
| created_at | DATE | NOT NULL |
Sample data:
| created_at | user_id | user_name |
|---|---|---|
| 2025-01-05 | 1 | Ava |
| 2025-01-06 | 2 | Ben |
| 2025-01-07 | 3 | Cleo |
| 2025-01-08 | 4 | Dev |
| 2025-01-09 | 5 | Eli |
| 2025-01-10 | 6 | Fay |
| 2025-01-11 | 7 | Gus |
| 2025-01-12 | 8 | Hana |
Table accounts
| column | type | constraints |
|---|---|---|
| account_id | INT | PRIMARY KEY |
| user_id | INT | NOT NULL |
| created_at | DATE | NOT NULL |
| last_visit_at | DATE |
Sample data:
| account_id | created_at | last_visit_at | user_id |
|---|---|---|---|
| 101 | 2025-02-01 | 2025-05-30 | 1 |
| 201 | 2025-02-02 | 2025-05-28 | 2 |
| 202 | 2025-02-15 | 2025-05-31 | 2 |
| 301 | 2025-02-03 | 2025-05-20 | 3 |
| 302 | 2025-03-01 | 2025-05-29 | 3 |
| 303 | 2025-03-20 | NULL | 3 |
| 401 | 2025-02-04 | 2025-05-01 | 4 |
| 402 | 2025-02-18 | 2025-05-15 | 4 |
| 403 | 2025-03-05 | 2025-05-21 | 4 |
| 404 | 2025-03-25 | 2025-05-31 | 4 |
| 501 | 2025-02-05 | 2025-04-30 | 5 |
| 502 | 2025-02-19 | 2025-05-10 | 5 |
| 503 | 2025-03-06 | 2025-05-11 | 5 |
| 504 | 2025-03-26 | 2025-05-12 | 5 |
| 505 | 2025-04-10 | 2025-05-13 | 5 |
| 601 | 2025-02-06 | 2025-05-05 | 6 |
| 602 | 2025-04-01 | 2025-05-25 | 6 |
| 801 | 2025-02-07 | 2025-05-22 | 8 |
| 802 | 2025-02-20 | 2025-05-23 | 8 |
| 803 | 2025-03-07 | 2025-05-24 | 8 |
| 804 | 2025-04-02 | 2025-05-25 | 8 |
Table notifications
| column | type | constraints |
|---|---|---|
| notification_id | INT | PRIMARY KEY |
| account_id | INT | |
| created_at | TIMESTAMP | NOT NULL |
| read_at | TIMESTAMP | |
| notification_type | VARCHAR(30) | NOT NULL |
Sample data:
| account_id | created_at | notification_id | notification_type | read_at |
|---|---|---|---|---|
| 201 | 2025-05-20 09:00:00 | 1 | promo | 2025-05-20 10:00:00 |
| 202 | 2025-05-31 08:00:00 | 2 | security | NULL |
| 301 | 2025-05-10 12:00:00 | 3 | system | 2025-05-10 12:05:00 |
| 302 | 2025-05-29 15:00:00 | 4 | promo | 2025-05-29 16:00:00 |
| 303 | 2025-05-30 11:00:00 | 5 | promo | 2025-05-30 11:10:00 |
| 505 | 2025-05-13 09:30:00 | 6 | system | NULL |
| 601 | 2025-05-01 07:00:00 | 7 | promo | 2025-05-01 07:05:00 |
| 602 | 2025-05-25 18:00:00 | 8 | security | 2025-05-26 08:00:00 |
| 804 | 2025-05-25 10:00:00 | 9 | promo | NULL |
| NULL | 2025-05-28 10:00:00 | 10 | system | NULL |
Expected output
One row with the number of multi-account users, how many of them have at least one unread notification, and the percentage (0-100) rounded to 2 decimals.
| pct_with_unread | total_multi_account_users | users_with_unread |
|---|---|---|
| 50 | 6 | 3 |
Hints
- Build the denominator first: users with at least 2 accounts.
- For the numerator, count distinct users who have at least one notification where
read_atis NULL.