Free resource - No login required
Free MySQL Take-Home Assignment Template for Data Engineer Hiring
Use this realistic MySQL work-sample assignment to screen data engineering, analytics engineering, and SQL-heavy candidates before technical interviews.
Includes MySQL schema, sample data, candidate instructions, expected outputs, and scoring rubric.
What's included
This free MySQL hiring assignment includes everything you need to run a structured technical screen.
- Candidate instructions
- MySQL schema
- Sample data (seed SQL)
- 3 realistic SQL tasks
- Expected output tables
- Reviewer scoring rubric
- Seniority calibration guidance
Who this template is for
This template is useful for teams hiring:
- Data engineers
- Analytics engineers
- BI developers
- Data analysts
- Backend engineers working with SQL-heavy systems
The assignment tests practical SQL reasoning, joins, aggregation, date handling, conditional logic, window functions, and ability to translate business requirements into correct SQL.
MySQL-specific skills tested
This assignment tests practical MySQL 8+ skills including TIMESTAMPDIFF, DATE_FORMAT, CAST, CASE expressions, aggregate functions, joins, grouping, rounding, common table expressions, and ROW_NUMBER window functions.
Assignment scenario
SaaS support operations analytics
Candidates are given a small support-ticket dataset for a SaaS company. The dataset contains customers, support agents, and tickets. The goal is to write MySQL 8+ queries that help the support team understand SLA breaches, agent performance, and customer ticket burden.
MySQL schema and sample data
Run this seed file to create the tables and load the sample dataset.
DROP TABLE IF EXISTS tickets;
DROP TABLE IF EXISTS agents;
DROP TABLE IF EXISTS customers;
CREATE TABLE customers (
customer_id INT PRIMARY KEY,
company_name VARCHAR(255) NOT NULL,
plan VARCHAR(50) NOT NULL
);
CREATE TABLE agents (
agent_id INT PRIMARY KEY,
agent_name VARCHAR(255) NOT NULL,
team VARCHAR(100) NOT NULL
);
CREATE TABLE tickets (
ticket_id INT PRIMARY KEY,
customer_id INT NOT NULL,
agent_id INT NOT NULL,
priority VARCHAR(20) NOT NULL,
created_at DATETIME NOT NULL,
first_response_at DATETIME NOT NULL,
resolved_at DATETIME NOT NULL,
reopened BOOLEAN NOT NULL DEFAULT FALSE,
CONSTRAINT fk_tickets_customer
FOREIGN KEY (customer_id) REFERENCES customers(customer_id),
CONSTRAINT fk_tickets_agent
FOREIGN KEY (agent_id) REFERENCES agents(agent_id),
CONSTRAINT chk_priority
CHECK (priority IN ('critical', 'high', 'normal'))
);
INSERT INTO customers (customer_id, company_name, plan) VALUES
(1, 'Northwind Analytics', 'Startup'),
(2, 'BluePeak Logistics', 'Growth'),
(3, 'Cedar Bank', 'Enterprise'),
(4, 'Luma Retail', 'Growth');
INSERT INTO agents (agent_id, agent_name, team) VALUES
(10, 'Ava', 'Platform'),
(11, 'Mihkel', 'Data'),
(12, 'Sara', 'Data');
INSERT INTO tickets (
ticket_id,
customer_id,
agent_id,
priority,
created_at,
first_response_at,
resolved_at,
reopened
) VALUES
(1001, 1, 10, 'high', '2025-01-03 09:00:00', '2025-01-03 13:30:00', '2025-01-04 10:00:00', FALSE),
(1002, 2, 11, 'normal', '2025-01-05 08:00:00', '2025-01-06 10:00:00', '2025-01-07 09:00:00', TRUE),
(1003, 3, 12, 'critical', '2025-01-08 14:00:00', '2025-01-08 19:00:00', '2025-01-09 14:00:00', FALSE),
(1004, 4, 11, 'high', '2025-01-10 10:00:00', '2025-01-10 17:00:00', '2025-01-11 12:00:00', FALSE),
(1005, 3, 10, 'normal', '2025-01-12 09:00:00', '2025-01-12 20:00:00', '2025-01-13 09:00:00', FALSE),
(1006, 2, 12, 'critical', '2025-01-18 11:00:00', '2025-01-18 16:30:00', '2025-01-19 11:00:00', TRUE),
(1007, 1, 10, 'normal', '2025-02-02 09:00:00', '2025-02-03 08:00:00', '2025-02-04 09:00:00', FALSE),
(1008, 2, 11, 'high', '2025-02-04 12:00:00', '2025-02-04 22:00:00', '2025-02-05 10:00:00', FALSE),
(1009, 4, 12, 'normal', '2025-02-06 09:00:00', '2025-02-07 12:00:00', '2025-02-08 09:00:00', FALSE),
(1010, 3, 10, 'critical', '2025-02-07 15:00:00', '2025-02-07 17:00:00', '2025-02-07 23:00:00', FALSE),
(1011, 3, 11, 'high', '2025-02-12 08:00:00', '2025-02-12 18:30:00', '2025-02-13 08:00:00', TRUE),
(1012, 2, 12, 'normal', '2025-02-16 09:00:00', '2025-02-16 20:00:00', '2025-02-17 09:00:00', FALSE);Candidate instructions
You are given a small SaaS support-ticket database.
Write MySQL 8+ queries to answer the tasks below. Use clear, readable SQL. You may use common table expressions, subqueries, aggregate functions, CASE expressions, and window functions.
Return exactly the columns requested in each task. Follow ordering and tie-breaking rules exactly.
SLA breach rate by month and plan
Support leadership wants to understand whether customers on different plans are receiving timely first responses.
SLA rules:
- critical tickets: first response within 4 hours
- high tickets: first response within 8 hours
- normal tickets: first response within 24 hours
Write a query that returns the SLA breach rate by month and customer plan.
Expected columns:
- month, plan, total_tickets, breached_tickets, breach_rate_pct
Rules:
monthshould be the first day of the month as a date.breach_rate_pctshould be rounded to 1 decimal place.- Order by month ascending, then plan ascending.
Solution query
SELECT
CAST(DATE_FORMAT(t.created_at, '%Y-%m-01') AS DATE) AS month,
c.plan,
COUNT(*) AS total_tickets,
SUM(
CASE
WHEN TIMESTAMPDIFF(MINUTE, t.created_at, t.first_response_at) >
CASE t.priority
WHEN 'critical' THEN 4 * 60
WHEN 'high' THEN 8 * 60
WHEN 'normal' THEN 24 * 60
END
THEN 1
ELSE 0
END
) AS breached_tickets,
ROUND(
SUM(
CASE
WHEN TIMESTAMPDIFF(MINUTE, t.created_at, t.first_response_at) >
CASE t.priority
WHEN 'critical' THEN 4 * 60
WHEN 'high' THEN 8 * 60
WHEN 'normal' THEN 24 * 60
END
THEN 1
ELSE 0
END
) * 100.0 / COUNT(*),
1
) AS breach_rate_pct
FROM tickets t
JOIN customers c
ON t.customer_id = c.customer_id
GROUP BY
CAST(DATE_FORMAT(t.created_at, '%Y-%m-01') AS DATE),
c.plan
ORDER BY
month,
c.plan;Expected output
| month | plan | total_tickets | breached_tickets | breach_rate_pct |
|---|---|---|---|---|
| 2025-01-01 | Enterprise | 2 | 1 | 50.0 |
| 2025-01-01 | Growth | 3 | 2 | 66.7 |
| 2025-01-01 | Startup | 1 | 0 | 0.0 |
| 2025-02-01 | Enterprise | 2 | 1 | 50.0 |
| 2025-02-01 | Growth | 3 | 2 | 66.7 |
| 2025-02-01 | Startup | 1 | 0 | 0.0 |
Agent resolution performance
The support manager wants to compare resolution speed for agents who resolved at least two tickets in January 2025.
Write a query that returns each qualifying agent's number of resolved tickets and average resolution time.
Expected columns:
- agent_id, agent_name, resolved_tickets, avg_resolution_hours
Rules:
- Include only tickets resolved in January 2025.
- Include only agents with at least 2 resolved tickets in that period.
avg_resolution_hoursshould be rounded to 1 decimal place.- Order by
avg_resolution_hoursascending, thenagent_idascending.
Solution query
SELECT
a.agent_id,
a.agent_name,
COUNT(*) AS resolved_tickets,
ROUND(
AVG(TIMESTAMPDIFF(MINUTE, t.created_at, t.resolved_at) / 60.0),
1
) AS avg_resolution_hours
FROM tickets t
JOIN agents a
ON t.agent_id = a.agent_id
WHERE t.resolved_at >= '2025-01-01 00:00:00'
AND t.resolved_at < '2025-02-01 00:00:00'
GROUP BY
a.agent_id,
a.agent_name
HAVING COUNT(*) >= 2
ORDER BY
avg_resolution_hours,
a.agent_id;Expected output
| agent_id | agent_name | resolved_tickets | avg_resolution_hours |
|---|---|---|---|
| 12 | Sara | 2 | 24.0 |
| 10 | Ava | 2 | 24.5 |
| 11 | Mihkel | 2 | 37.5 |
Highest customer burden by month
Support leadership wants to know which customer generated the highest support burden in each month.
Burden scoring:
- critical ticket = 5 points
- high ticket = 3 points
- normal ticket = 1 point
Write a query that returns the customer with the highest burden score for each month.
Expected columns:
- month, customer_id, company_name, burden_score
Rules:
monthshould be the first day of the month as a date.- If two customers have the same burden score in a month, return the customer with the lower
customer_id. - Order by month ascending.
Solution query
WITH customer_monthly_burden AS (
SELECT
CAST(DATE_FORMAT(t.created_at, '%Y-%m-01') AS DATE) AS month,
c.customer_id,
c.company_name,
SUM(
CASE t.priority
WHEN 'critical' THEN 5
WHEN 'high' THEN 3
WHEN 'normal' THEN 1
END
) AS burden_score
FROM tickets t
JOIN customers c
ON t.customer_id = c.customer_id
GROUP BY
CAST(DATE_FORMAT(t.created_at, '%Y-%m-01') AS DATE),
c.customer_id,
c.company_name
),
ranked AS (
SELECT
customer_monthly_burden.*,
ROW_NUMBER() OVER (
PARTITION BY month
ORDER BY burden_score DESC, customer_id ASC
) AS rn
FROM customer_monthly_burden
)
SELECT
month,
customer_id,
company_name,
burden_score
FROM ranked
WHERE rn = 1
ORDER BY month;Expected output
| month | customer_id | company_name | burden_score |
|---|---|---|---|
| 2025-01-01 | 2 | BluePeak Logistics | 6 |
| 2025-02-01 | 3 | Cedar Bank | 8 |
Reviewer scoring rubric
Score the assignment out of 30 points, 10 points per task.
| Dimension | Points | What to check |
|---|---|---|
| Correctness | 5 | Returns correct rows and columns, handles joins and grouping correctly, follows ordering rules |
| SQL quality | 2 | Readable structure, useful aliases, avoids unnecessary complexity, uses MySQL 8+ features appropriately |
| Edge cases | 2 | Handles SLA thresholds, month grouping, and tie-breaking correctly where required |
| Communication | 1 | Query is easy for reviewers to understand; logic is clear enough to discuss in an interview |
Suggested interpretation
How to use this manually
You can use this template manually by copying the schema and sample data into a MySQL 8+ database, sending the task descriptions to candidates, and reviewing their submitted SQL against the expected outputs and rubric.
This resource is intentionally ungated. You can adapt the dataset, tasks, or scoring rubric to match your own hiring process.
Validation commands
mysql "$MYSQL_DATABASE_URL" < mysql_seed.sql
mysql "$MYSQL_DATABASE_URL" < mysql_task_1_solution.sql
mysql "$MYSQL_DATABASE_URL" < mysql_task_2_solution.sql
mysql "$MYSQL_DATABASE_URL" < mysql_task_3_solution.sqlNeed another SQL dialect?
This is the MySQL version of the SQL take-home assignment template. You can also use:
Want to create your own SQL assessment?
How Datakaru helps
Datakaru helps hiring teams create custom SQL and Python take-home assignments, send them to candidates, and review submissions with AI-assisted scoring.
Use this template as a starting point, then build your own assessment in Datakaru based on your role, dataset, and hiring criteria.
No credit card required - 14-day free trial
Frequently asked questions
- What is a MySQL take-home assignment?
- A MySQL take-home assignment is a practical hiring task where candidates write MySQL queries against a sample database or realistic dataset. It helps hiring teams evaluate job-relevant SQL skills before a technical interview.
- What should a MySQL hiring test evaluate?
- A good MySQL hiring test should evaluate joins, filtering, aggregation, date handling, conditional logic, tie-breaking, and the candidate's ability to translate business questions into correct SQL.
- How long should a SQL take-home assignment take?
- For early screening, 30 to 60 minutes is usually enough. Longer assignments may create unnecessary candidate burden unless the role is senior or highly specialized.
- Can this template be used for data engineer hiring?
- Yes. This template is suitable for data engineer, analytics engineer, BI developer, and SQL-heavy analyst roles.
- Can I use this assignment in Datakaru?
- You can use this template manually, or use Datakaru to create your own custom SQL and Python take-home assignments for candidates.
Ready to run better technical screens?
Use this template as-is, or build your own custom SQL assignment in Datakaru.