SQL games guide

SQL Murder Mystery: hints, walkthrough and solution

The SQL Murder Mystery is a free browser game from the Knight Lab at Northwestern University. There was a murder in SQL City on January 15, 2018, and you find the killer with SQL queries on a police database. To start, open mystery.knightlab.com and query the crime_scene_report table. If you are stuck, open the hints for your step. Each step also shows its query and its real result.

By Owen Middleton Updated October 2026 Every query run on the game's database
Show the answer: who is the killer?

The killer is Jeremy Bowers. The person who hired him is Miranda Priestly. The game has two parts: part 1 finds the killer, and part 2 finds the person behind the murder.

Where are you stuck in the SQL Murder Mystery?

Find the line that matches what you have now in the SQL Murder Mystery, and go to that step.

What you have nowGo to
You have the prompt, and you have not run a query yet.Part 1, step 1: Find the crime scene report
A crime scene report that describes two witnesses.Part 1, step 2: Find the first witness
The first witness: person 14887, at the last house on Northwestern Dr.Part 1, step 3: Find the second witness
The ids of both witnesses, 14887 and 16371.Part 1, step 4: Read the two interviews
Two interview transcripts: a gym bag, a 48Z membership, a car plate with H42W.Part 1, step 5: Check the gym clue
Two gold 48Z gym members who were at the gym on January 9.Part 1, step 6: Check the car plate
Three people with an H42W car plate.Part 1, step 7: Put the clues in one query
The game replied "Congrats, you found the murderer! But wait, there's more..."Part 2, step 1: Read the killer's interview
The killer's interview: a red-haired woman with a Tesla Model S.Part 2, step 2: Find the women who match the description
Three red-haired women who drive a Tesla Model S.Part 2, step 3: Find who went to the concert 3 times
Two people who went to the SQL Symphony Concert 3 times in December 2017.Part 2, step 4: Put the clues in one query

How do you play the SQL Murder Mystery?

You play the SQL Murder Mystery in your browser, with no account and no install. You play in five steps:

  1. Open mystery.knightlab.com and read the prompt: a murder, on January 15, 2018, in SQL City.
  2. Look at the tables. The game runs on SQLite, so SELECT name FROM sqlite_master WHERE type = 'table' lists them. The page also has a schema diagram.
  3. Write a query in one of the boxes and run it. Each result gives you a clue for the next query.
  4. Follow the clues through the tables until one person is left.
  5. Check your answer with the game's solution table.

To check an answer, run these two statements with the name that you found:

INSERT INTO solution VALUES (1, 'Name Here');
SELECT value FROM solution;

A wrong name gets the reply "That's not the right person. Try again!" The killer's name gets "Congrats, you found the murderer! But wait, there's more..." and that reply starts part 2.

What tables are in the SQL Murder Mystery database?

The SQL Murder Mystery database has 9 tables. Most of the case is about connecting them by their ids, so keep this list open while you play.

TableWhat it holdsColumns that link
crime_scene_reportPolice reports: date (a number such as 20180115), type of crime, a description and the city.
personEvery person: name, address and the ids that link to other tables.id, license_id, ssn
interviewWhat people told the police.person_id
drivers_licenseAge, height, eye and hair color, gender, car and plate number.id
get_fit_now_memberMembers of the Get Fit Now Gym and their membership status.id (such as 48Z55), person_id
get_fit_now_check_inEach gym visit, with the date and times.membership_id
facebook_event_checkinEach check-in at an event, with the event name and date.person_id
incomeAnnual income.ssn
solutionWhere you put your answer to check it.

The links between tables: person.license_id = drivers_license.id, person.ssn = income.ssn, and person_id in the other tables = person.id. A gym visit links to a member by membership_id = get_fit_now_member.id.

Why does my SQL Murder Mystery query return no rows?

A SQL Murder Mystery query returns no rows when a filter does not match the data exactly. Look at three things first: the dates are numbers such as 20180115, the = sign matches letter case exactly, and a LIKE pattern can be too narrow. Each item is a wrong turn, with what you get and what to write.

  • You typed date = '2018-01-15'

    You get 0 rows

    Write date = 20180115

    The date column is a number, not a date, so text never matches it. See Part 1, step 1.

  • You typed type = 'Murder' or city = 'sql city'

    You get 0 rows

    Write type = 'murder' AND city = 'SQL City'

    With =, the letter case must match the data exactly. See Part 1, step 1.

  • You typed address_street_name = 'Northwestern Drive'

    You get 0 rows

    Write address_street_name = 'Northwestern Dr'

    The data uses the short form of the street name, as the report does. See Part 1, step 2.

  • You typed ORDER BY address_number LIMIT 1

    You get the wrong person: Kinsey Erickson, house 309

    Write ORDER BY address_number DESC LIMIT 1

    Without DESC, the sort goes from low to high, so you get the first house, not the last. See Part 1, step 2.

  • You typed name = 'Annabel'

    You get 0 rows

    Write name LIKE 'Annabel%'

    The name column holds full names, so the first name alone matches nobody. See Part 1, step 3.

  • You typed check_in_date = '2018-01-09'

    You get 0 rows

    Write check_in_date = 20180109

    Gym dates are numbers too. See Part 1, step 5.

  • You typed plate_number LIKE 'H42W%'

    You get one plate, H42W0X, and the driver is a woman

    Write plate_number LIKE '%H42W%'

    The witness said the plate includes H42W, not that it starts with H42W. The pattern without the first % finds only one plate, and it belongs to a woman. See Part 1, step 6.

  • You typed hair_color = 'Red' or car_model = 'Tesla Model S'

    You get 0 rows

    Write hair_color = 'red' AND car_make = 'Tesla' AND car_model = 'Model S'

    Hair colors are lowercase, and the make and the model are two columns. See Part 2, step 2.

  • You typed WHERE event_name = 'SQL Symphony Concert' (no date)

    You get 25 people with 3 visits, not 2

    Write date BETWEEN 20171201 AND 20171231

    Without the date filter, you count visits from all of the data, not from December 2017. See Part 2, step 3.

SQL Murder Mystery walkthrough, part 1: who is the killer?

The killer in the SQL Murder Mystery is one man, and 7 queries get you from the crime scene report to his name. Each step shows a first hint. Open the second hint, and then the query, only when you need them.

Part 1, step 1: Find the crime scene report

Get the report for the murder on January 15, 2018, in SQL City.

Hint 1: The report is in the crime_scene_report table. The prompt gives you three facts that pick one row.

Hint 2

Filter on date, type and city. The date column is a number in the form 20180115, not a date. Without the city filter, the query returns 3 murders on that date: in Albany, Reno and SQL City.

Show the query and the result
SELECT *
FROM crime_scene_report
WHERE date = 20180115
  AND type = 'murder'
  AND city = 'SQL City';
datetypedescriptioncity
20180115murderSecurity footage shows that there were 2 witnesses. The first witness lives at the last house on "Northwestern Dr". The second witness, named Annabel, lives somewhere on "Franklin Ave".SQL City

What you learn: Two witnesses: the last house on Northwestern Dr, and a person named Annabel on Franklin Ave.

Part 1, step 2: Find the first witness

Find the person who lives at the last house on Northwestern Dr.

Hint 1: Addresses are in the person table, in the columns address_number and address_street_name.

Hint 2

50 people live on Northwestern Dr. The last house has the highest address_number, so sort from high to low and keep the first row.

Show the query and the result
SELECT id, name, address_number, address_street_name
FROM person
WHERE address_street_name = 'Northwestern Dr'
ORDER BY address_number DESC
LIMIT 1;
idnameaddress_numberaddress_street_name
14887Morty Schapiro4919Northwestern Dr

What you learn: The first witness is person 14887.

Part 1, step 3: Find the second witness

Find the person named Annabel who lives on Franklin Ave.

Hint 1: Use the person table again. You know only the first name, so match the start of the name.

Hint 2

LIKE 'Annabel%' matches every name that starts with Annabel. 4 people match it, so also filter on the street.

Show the query and the result
SELECT id, name, address_number, address_street_name
FROM person
WHERE address_street_name = 'Franklin Ave'
  AND name LIKE 'Annabel%';
idnameaddress_numberaddress_street_name
16371Annabel Miller103Franklin Ave

What you learn: The second witness is person 16371.

Part 1, step 4: Read the two interviews

Read what the two witnesses told the police.

Hint 1: The interview table has a person_id column. Use the two ids that you found.

Hint 2

IN (14887, 16371) matches both ids in one query.

Show the query and the result
SELECT person_id, transcript
FROM interview
WHERE person_id IN (14887, 16371);
person_idtranscript
14887I heard a gunshot and then saw a man run out. He had a "Get Fit Now Gym" bag. The membership number on the bag started with "48Z". Only gold members have those bags. The man got into a car with a plate that included "H42W".
16371I saw the murder happen, and I recognized the killer from my gym when I was working out last week on January the 9th.

What you learn: The killer is a man, a gold member of Get Fit Now Gym with a membership id that starts with 48Z. The second witness saw him at the gym on January 9. His car plate includes H42W.

Part 1, step 5: Check the gym clue

Find the gold members with a 48Z id who were at the gym on January 9, 2018.

Hint 1: Members are in get_fit_now_member. Visits are in get_fit_now_check_in. The two tables share the membership id.

Hint 2

Join the tables on get_fit_now_check_in.membership_id = get_fit_now_member.id. Then filter on the id, the gold status and check_in_date = 20180109.

Show the query and the result
SELECT get_fit_now_member.id, get_fit_now_member.name,
       get_fit_now_member.membership_status
FROM get_fit_now_member
JOIN get_fit_now_check_in
  ON get_fit_now_check_in.membership_id = get_fit_now_member.id
WHERE get_fit_now_member.id LIKE '48Z%'
  AND get_fit_now_member.membership_status = 'gold'
  AND get_fit_now_check_in.check_in_date = 20180109;
idnamemembership_status
48Z7AJoe Germuskagold
48Z55Jeremy Bowersgold

What you learn: Two members match, so the gym clue alone does not decide. Use the car plate.

Part 1, step 6: Check the car plate

Find the people whose car plate includes H42W.

Hint 1: Plates are in drivers_license. Names are in person. person.license_id points to drivers_license.id.

Hint 2

LIKE '%H42W%' matches H42W at any position in the plate.

Show the query and the result
SELECT person.name, drivers_license.plate_number, drivers_license.gender
FROM person
JOIN drivers_license ON drivers_license.id = person.license_id
WHERE drivers_license.plate_number LIKE '%H42W%';
nameplate_numbergender
Tushar Chandra4H42WRmale
Jeremy Bowers0H42W2male
Maxine WhitelyH42W0Xfemale

What you learn: One name is in both lists: Jeremy Bowers.

Part 1, step 7: Put the clues in one query

Get the one person who has an H42W plate and a gold membership with a 48Z id.

Hint 1: Join three tables: person, drivers_license and get_fit_now_member.

Hint 2

get_fit_now_member.person_id points to person.id. Keep the plate filter, the 48Z id filter and the gold filter.

Show the query and the result
SELECT person.id, person.name
FROM person
JOIN drivers_license ON drivers_license.id = person.license_id
JOIN get_fit_now_member ON get_fit_now_member.person_id = person.id
WHERE drivers_license.plate_number LIKE '%H42W%'
  AND get_fit_now_member.id LIKE '48Z%'
  AND get_fit_now_member.membership_status = 'gold';
idname
67318Jeremy Bowers

What you learn: The killer is Jeremy Bowers, person 67318.

SQL Murder Mystery walkthrough, part 2: who hired the killer?

Part 2 of the SQL Murder Mystery starts from the killer's interview, and it ends with the name of the person who paid him. Each step shows a first hint, and the query is one click further.

Part 2 in 2 queries

The game challenges you to finish part 2 in no more than 2 queries. You can:

  1. Read the killer's interview: Part 2, step 1: Read the killer's interview.
  2. Put every clue in one query, with a subquery for the concert: Part 2, step 4: Put the clues in one query.

Steps 2 and 3 show the same clues one at a time, if you want to see each list first.

Part 2, step 1: Read the killer's interview

Read what Jeremy Bowers told the police.

Hint 1: Use the interview table with his person id.

Hint 2

His person id is 67318.

Show the query and the result
SELECT transcript
FROM interview
WHERE person_id = 67318;
transcript
I was hired by a woman with a lot of money. I don't know her name but I know she's around 5'5" (65") or 5'7" (67"). She has red hair and she drives a Tesla Model S. I know that she attended the SQL Symphony Concert 3 times in December 2017.

What you learn: A woman, 65 to 67 inches tall, red hair, a Tesla Model S, at the SQL Symphony Concert 3 times in December 2017.

Part 2, step 2: Find the women who match the description

Find the drivers who match her height, hair and car.

Hint 1: Height, hair color, gender and car are all columns of drivers_license.

Hint 2

BETWEEN 65 AND 67 keeps both ends. Without the height filter, 3 drivers still match, so you need the concert clue too.

Show the query and the result
SELECT person.id, person.name, drivers_license.height
FROM person
JOIN drivers_license ON drivers_license.id = person.license_id
WHERE drivers_license.gender = 'female'
  AND drivers_license.hair_color = 'red'
  AND drivers_license.car_make = 'Tesla'
  AND drivers_license.car_model = 'Model S'
  AND drivers_license.height BETWEEN 65 AND 67;
idnameheight
78881Red Korb65
90700Regina George66
99716Miranda Priestly66

What you learn: Three women match. The concert clue decides.

Part 2, step 3: Find who went to the concert 3 times

Find the people who checked in at the SQL Symphony Concert 3 times in December 2017.

Hint 1: Check-ins are in facebook_event_checkin, one row for each check-in.

Hint 2

Count the rows for each person_id with GROUP BY, and keep the groups where the count is 3 with HAVING.

Show the query and the result
SELECT person_id, COUNT(*) AS visits
FROM facebook_event_checkin
WHERE event_name = 'SQL Symphony Concert'
  AND date BETWEEN 20171201 AND 20171231
GROUP BY person_id
HAVING COUNT(*) = 3;
person_idvisits
245563
997163

What you learn: Person 99716 is in both lists: Miranda Priestly.

Part 2, step 4: Put the clues in one query

Get the one woman with red hair and a Tesla Model S who went to the concert 3 times.

Hint 1: Put the concert query inside the description query as a subquery.

Hint 2

Use person.id IN (the concert query). Join income on ssn if you want to see her money too.

Show the query and the result
SELECT person.name, income.annual_income
FROM person
JOIN drivers_license ON drivers_license.id = person.license_id
JOIN income ON income.ssn = person.ssn
WHERE drivers_license.gender = 'female'
  AND drivers_license.hair_color = 'red'
  AND drivers_license.car_make = 'Tesla'
  AND drivers_license.car_model = 'Model S'
  AND person.id IN (
    SELECT person_id
    FROM facebook_event_checkin
    WHERE event_name = 'SQL Symphony Concert'
      AND date BETWEEN 20171201 AND 20171231
    GROUP BY person_id
    HAVING COUNT(*) = 3
  );
nameannual_income
Miranda Priestly310000

What you learn: The person who hired the killer is Miranda Priestly.

Which SQL do you need for the SQL Murder Mystery?

You can solve the SQL Murder Mystery with WHERE, LIKE and one join at a time. The walkthrough also joins three tables and uses GROUP BY, HAVING and one subquery, so that each step is one query. Each row names the first walkthrough step that uses the SQL, with a free lesson for it.

SQLFirst used inFree lesson
WHEREPart 1, step 1: Find the crime scene reportWHERE
ANDPart 1, step 1: Find the crime scene reportAND, OR and NOT
ORDER BYPart 1, step 2: Find the first witnessORDER BY
LIMITPart 1, step 2: Find the first witnessLIMIT
LIKEPart 1, step 3: Find the second witnessBETWEEN, IN and LIKE
INPart 1, step 4: Read the two interviewsBETWEEN, IN and LIKE
INNER JOINPart 1, step 5: Check the gym clueINNER JOIN
A join on three tablesPart 1, step 7: Put the clues in one queryJoins on more than two tables
BETWEENPart 2, step 2: Find the women who match the descriptionBETWEEN, IN and LIKE
GROUP BYPart 2, step 3: Find who went to the concert 3 timesGROUP BY
HAVINGPart 2, step 3: Find who went to the concert 3 timesHAVING
A subquery in WHEREPart 2, step 4: Put the clues in one querySubqueries in WHERE

What should you play after the SQL Murder Mystery?

After the SQL Murder Mystery, play SQL Block Game. The murder case uses WHERE in every step, and ORDER BY, LIMIT and GROUP BY too. SQL Block Game drills those clauses at speed. Query cards fall, and you write the SQL that answers each one before it lands. It runs real PostgreSQL in your browser, it is free, and every run shuffles the cards.

Play SQL Block Game →

For more detective games and how they compare, read our ranking of the best SQL games. For a story that teaches window functions and recursive CTEs, play Station Zero.

SQL Murder Mystery questions

Who made the SQL Murder Mystery?

Joon Park and Cathy He made it while they were fellows at the Knight Lab of Northwestern University. Joe Germuska made the web version. The game is free, and you play it in your browser.

Can you play the SQL Murder Mystery offline?

Yes. Download the file sql-murder-mystery.db from the game’s GitHub repository and open it in a SQLite tool. The repository suggests SQLiteStudio.

Do the SQL Murder Mystery queries work in PostgreSQL?

The 11 walkthrough queries return the same rows in PostgreSQL 17.5 with the game data loaded. Four things from the game do not work the same way. PostgreSQL has no sqlite_master table, so use information_schema.tables to list tables. PostgreSQL reads "SQL City" in double quotes as a column name, so put text in single quotes. LIKE 'annabel%' finds 4 people in the game, but 0 in PostgreSQL, because PostgreSQL LIKE does not ignore case. And the answer check is a SQLite trigger in the game's database file, so it does not exist in PostgreSQL.

How long does the SQL Murder Mystery take?

About 45 minutes, in our own play. If you get stuck, open the hints for the step you are on.

The SQL Murder Mystery is by Joon Park and Cathy He, Northwestern University Knight Lab. The case text and the database rows quoted on this page are from the game's GitHub repository and are licensed CC BY-SA 4.0. SQLMaxx did not make this game.