cswork / libraryOpen practice workspace

Coding questions · Meta

Write SQL to flag coordinated fake accounts

This question evaluates proficiency in SQL-based data manipulation, temporal windowing, event-table joins, aggregation and feature engineering for fraud detection, including computing weighted risk_score flags across user activity.

Assume today is 2025-09-01. Schema and tiny samples:

users(user_id, created_at, country)
1 | 2025-07-01 | US
2 | 2025-08-10 | IN
3 | 2025-08-15 | US
4 | 2025-08-20 | RU
logins(user_id, login_time, ip, country, device_id)
1 | 2025-08-31 10:00 | 1.1.1.1 | US | d1
1 | 2025-08-31 22:00 | 2.2.2.2 | DE | d2
3 | 2025-08-31 10:05 | 3.3.3.3 | US | d3
4 | 2025-08-31 02:00 | 4.4.4.4 | RU | d4
4 | 2025-08-31 02:30 | 5.5.5.5 | BR | d5
friend_requests(sender_id, receiver_id, sent_time, accepted, accepted_time)
1 | 3 | 2025-08-10 | true | 2025-08-12
4 | 1 | 2025-08-25 | false | null
4 | 2 | 2025-08-25 | false | null
2 | 3 | 2025-08-26 | true | 2025-08-27
messages(sender_id, receiver_id, sent_time)
4 | 1 | 2025-08-31 02:05
4 | 2 | 2025-08-31 02:06
4 | 3 | 2025-08-31 02:07
posts(post_id, user_id, created_time)
10 | 1 | 2025-08-30 09:00
11 | 4 | 2025-08-31 02:10
devices(device_id, user_id, device_type)
d1 | 1 | iOS
d2 | 1 | Android
d3 | 3 | Web
d4 | 4 | Android
d5 | 4 | iOS

Task: Write a single SQL query (CTEs allowed) that outputs user_id and three feature flags for the last 7 days (2025-08-26 to 2025-09-01): F1=1 if within any 24h window the user logs in from ≥3 distinct countries; F2=1 if within 5 minutes of account creation the user messages ≥3 distinct recipients; F3=1 if in the last 7 days the user sent ≥20 friend requests and acceptance rate <10%. Also output a risk_score = 0.5F1 + 0.3F2 + 0.2*F3. Return only users with risk_score ≥0.5.

Write SQL to flag coordinated fake accounts

Assume the current date is 2025-06-01.

You are given the following tables:

  • users(user_id, created_at, country)
  • logins(user_id, login_time, ip, country, device_id)
  • friend_requests(sender_id, receiver_id, sent_time, accepted, accepted_time)
  • messages(sender_id, receiver_id, sent_time)
  • posts(post_id, user_id, created_time)
  • devices(device_id, user_id, device_type)

Using these tables, write a single SQL query (CTEs allowed) that outputs, for each user, the fields user_id, F1, F2, F3, and risk_score, where:

• Consider the 7-day period from 2025-05-26 to 2025-06-01 (inclusive).

• F1 = 1 if, using only login rows with login_time between '2025-05-26 00:00:00' and '2025-06-01 23:59:59', there exists at least one 24-hour window in which that user logs in from 3 or more distinct countries; otherwise F1 = 0.

• F2 = 1 if, within 5 minutes of the account creation time (created_at), the user sends messages to 3 or more distinct recipients (receiver_id); otherwise F2 = 0. (This condition is independent of the 7-day window; it uses all messages relative to created_at.)

• F3 = 1 if, considering only friend_requests with sent_time between '2025-05-26 00:00:00' and '2025-06-01 23:59:59', the user (as sender_id) sends at least 20 friend requests and their acceptance rate in that period is less than 10% (acceptance rate = accepted requests / total requests); otherwise F3 = 0.

Compute a risk_score for each user as: risk_score = 0.5 * F1 + 0.3 * F2 + 0.2 * F3

Return only users with risk_score >= 0.5.

Write a single SQL query that produces this result.

Table users

columntypeconstraints
user_idINTPRIMARY KEY, NOT NULL
created_atTIMESTAMPNOT NULL
countryVARCHAR(2)NOT NULL

Sample data:

countrycreated_atuser_id
US2025-05-01 10:00:001
IN2025-05-27 09:00:002
US2025-05-30 11:00:003
RU2025-05-31 02:00:004

Table logins

columntypeconstraints
user_idINTNOT NULL
login_timeTIMESTAMPNOT NULL
ipVARCHAR(45)NOT NULL
countryVARCHAR(2)NOT NULL
device_idVARCHAR(10)NOT NULL

Sample data:

countrydevice_idiplogin_timeuser_id
USd11.1.1.12025-05-30 10:00:001
DEd22.2.2.22025-05-30 18:00:001
FRd13.3.3.32025-05-31 09:00:001
INd34.4.4.42025-05-29 09:30:002
USd35.5.5.52025-05-29 15:00:002
DEd46.6.6.62025-05-30 08:00:002
USd57.7.7.72025-05-27 10:00:003
USd58.8.8.82025-05-31 10:00:003
RUd69.9.9.92025-05-31 02:00:004
BRd710.10.10.102025-05-31 02:30:004

Table friend_requests

columntypeconstraints
sender_idINTNOT NULL
receiver_idINTNOT NULL
sent_timeTIMESTAMPNOT NULL
acceptedBOOLEANNOT NULL
accepted_timeTIMESTAMP

Sample data:

acceptedaccepted_timereceiver_idsender_idsent_time
true2025-05-27 09:00:00312025-05-27 08:00:00
falseNULL142025-05-31 02:05:00
falseNULL122025-05-26 10:00:00
falseNULL322025-05-26 11:00:00
falseNULL422025-05-26 12:00:00
falseNULL122025-05-27 09:15:00
falseNULL322025-05-27 09:30:00
falseNULL422025-05-27 09:45:00
falseNULL122025-05-28 10:00:00
falseNULL322025-05-28 10:15:00
falseNULL422025-05-28 10:30:00
falseNULL122025-05-29 11:00:00
falseNULL322025-05-29 11:15:00
falseNULL422025-05-29 11:30:00
falseNULL122025-05-30 12:00:00
falseNULL322025-05-30 12:15:00
falseNULL422025-05-30 12:30:00
falseNULL122025-05-31 13:00:00
falseNULL322025-05-31 13:15:00
falseNULL422025-05-31 13:30:00
true2025-06-01 10:00:00122025-06-01 09:00:00
falseNULL322025-06-01 09:30:00

Table messages

columntypeconstraints
sender_idINTNOT NULL
receiver_idINTNOT NULL
sent_timeTIMESTAMPNOT NULL

Sample data:

receiver_idsender_idsent_time
142025-05-31 02:01:00
242025-05-31 02:02:00
342025-05-31 02:03:00
122025-05-27 10:30:00

Table posts

columntypeconstraints
post_idINTPRIMARY KEY, NOT NULL
user_idINTNOT NULL
created_timeTIMESTAMPNOT NULL

Sample data:

created_timepost_iduser_id
2025-05-30 09:00:00101
2025-05-31 02:10:00114

Table devices

columntypeconstraints
device_idVARCHAR(10)PRIMARY KEY, NOT NULL
user_idINTNOT NULL
device_typeVARCHAR(20)NOT NULL

Sample data:

device_iddevice_typeuser_id
d1iOS1
d2Android1
d3Web2
d4Android2
d5Web3
d6Android4
d7iOS4

Expected output

For the sample data, users 1 and 2 meet the risk threshold. User 1 has F1=1 (3 countries in a 24-hour login window) and F2=0, F3=0, giving risk_score=0.5. User 2 has F1=1 and F3=1 (at least 20 friend requests with <10% acceptance), F2=0, giving risk_score=0.7. Users 3 and 4 do not reach risk_score >= 0.5.

F1F2F3risk_scoreuser_id
1000.51
1010.72

Hints

  1. For F1, consider a self-join on the logins table (restricted to the 7-day window) to count distinct countries in a rolling 24-hour window per user.
  2. For F3, compute acceptance rate as AVG(CASE WHEN accepted THEN 1.0 ELSE 0.0 END) over friend_requests in the 7-day window, and then apply the count and rate thresholds.