Write SQL for character safety and engagement metrics
Character.AIData Scientist · Technical ScreenLast updated
This question evaluates proficiency in SQL-based data manipulation and analytics, specifically aggregations, joins, date-based grouping, ratio calculations, and windowed moving averages to compute safety and engagement metrics.
You are working with a conversational product that has users, AI characters, and conversations. Write SQL queries for each of the tasks below.
Assume UTC timestamps and that day means DATE(created_at).
Tables
users
user_idBIGINT PRIMARY KEYcreated_atTIMESTAMP
characters
character_idBIGINT PRIMARY KEYcreated_by_user_idBIGINT REFERENCESusers(user_id)created_atTIMESTAMPsafety_flagBOOLEANTRUE= safe,FALSE= unsafe
conversations
Each row represents a user engaging in a conversation associated with a character.
conversation_idBIGINTcharacter_idBIGINT REFERENCEScharacters(character_id)user_idBIGINT REFERENCESusers(user_id)created_atTIMESTAMPsafety_flagBOOLEANTRUE= safe,FALSE= unsafe
Notes:
- A single
conversation_idmay appear multiple times if multiple users engaged.
Task 1: Find the “top 100 characters”
Define “top” as the characters with the largest number of conversation engagements (rows in conversations) across all time.
Return:
character_idengagement_count
Order by engagement_count DESC and return only the top 100.
Task 2: Compute the unsafe character ratio
Compute the overall ratio of unsafe characters among all characters.
Return:
unsafe_character_ratio(a decimal between 0 and 1)
Where:
- unsafe character =
characters.safety_flag = FALSE
Task 3: 7-day moving average of daily unsafe-character percentage
For each day (based on characters.created_at), compute:
daily_unsafe_pct= (# characters created that day that are unsafe) / (total # characters created that day)- A 7-day trailing moving average of
daily_unsafe_pct(including the current day).
Return:
daydaily_unsafe_pctdaily_unsafe_pct_ma7
Order by day ascending.
Task 4 (open-ended, but answer with SQL outputs)
4a) Relationship between unsafe characters and unsafe conversations
Create a 2×2 breakdown of conversation engagements by:
- character safety (
characters.safety_flag) - conversation safety (
conversations.safety_flag)
Return:
character_safety_flagconversation_safety_flagengagement_count
4b) By day, unsafe-user engagement in unsafe conversations
For each day (based on conversations.created_at), compute metrics related to users who engaged in unsafe conversations (conversations.safety_flag = FALSE).
Return:
dayunsafe_conversation_engagements(count of rows whereconversations.safety_flag = FALSE)unsafe_users(distinct users engaging in unsafe conversations)total_engagements(all conversation rows that day)total_users(distinct users that day)unsafe_engagement_ratio=unsafe_conversation_engagements / total_engagementsunsafe_user_ratio=unsafe_users / total_users
Order by day ascending.
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.