Post

Walkthrough — SQL Murder Mystery

SQL Murder Mystery is an interactive learning experience that combines SQL querying with a captivating detective narrative. Players take on the role of a detective tasked with solving a murder case by analyzing a SQL database containing various tables, such as crime scene reports, witness statements, and city records. By writing and executing SQL queries, participants uncover clues, establish connections, and ultimately identify the murderer. This engaging approach not only enhances SQL skills but also makes learning data analysis and querying techniques enjoyable and immersive.

Walkthrough of SQL Murder Mystery : https://mystery.knightlab.com/


Crime: Murder at SQL City occurred on Jan. 15 2018. Goal: Find the murderer of SQL City

Finding the murderer

Retrieving the witnesses id

2 witnesses

  • 1st witness lives at the last home of Northwestern Dr
    1
    
    select * from person where (address_street_name="Northwestern Dr") order by address_number DESC limit 1;
    
idnamelicense_idaddress_numberaddress_street_namessn
14887Morty Schapiro1180094919Northwestern Dr111564949
  • 2nd witness named Annabel lives on Franklin Ave
    1
    
    select * from person where (address_street_name="Franklin Ave" and name like "Annabel %");
    
idnamelicense_idaddress_numberaddress_street_namessn
16371Annabel Miller490173103Franklin Ave318771143

Finding the interview of the witnesses

1
2
3
4
select person.id, person.name, interview.transcript from person
inner join interview
on person.id=interview.person_id
where (id=14887 or id=16371);
idnametranscript
14887Morty SchapiroI 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”.
16371Annabel MillerI saw the murder happen, and I recognized the killer from my gym when I was working out last week on January the 9th.

1st witness

  • Heard a gunshot
  • Suspect wore a “get Fit Now Gym” bag => Own only by gold members
  • Membership number starts with "48Z"
  • Disappeared in a car with plate that included "H42W"

2nd witness

  • Saw the murder happen
  • Recognized the murdered from her gym
  • Was working out on Jan. 9th 2018

Retrieving evidences from “Get Fit Now Gym”

  • Getting Annabel gym id
1
select id, person_id, name from get_fit_now_member where person_id=16371;
idperson_idname
9008116371Annabel Miller

id=90081

  • Getting Annabel’s check in check out time
1
2
3
4
5
select * from get_fit_now_check_in
inner join get_fit_now_member
on get_fit_now_member.id = get_fit_now_check_in.membership_id 
where get_fit_now_member.person_id=16371 
and get_fit_now_check_in.check_in_date = 20180109;
membership_idcheck_in_datecheck_in_timecheck_out_timeidperson_idnamemembership_start_date
9008120180109160017009008116371Annabel Miller20160208

check_in_time=1600 (16h) | check_out_time=1700 (17h)

  • Getting all people present during this time slot (with gold membership +id starts with “48Z”) Many combinations (<16 and >17 || >16 and <17 ||…), we will just try to get the people present the same day and visually select the corresponding people.
1
2
3
4
5
6
select * from get_fit_now_check_in
inner join get_fit_now_member
on get_fit_now_check_in.membership_id = get_fit_now_member.id
where get_fit_now_check_in.check_in_date=20180109
and get_fit_now_member.membership_status="gold"
and get_fit_now_member.id like "48Z%";
membership_idcheck_in_datecheck_in_timecheck_out_timeidperson_idnamemembership_start_datemembership_status
48Z7A201801091600173048Z7A28819Joe Germuska20160305gold
48Z55201801091530170048Z5567318Jeremy Bowers20160101gold

Two suspects: Joe Germuska id=28819 membership_id=48Z7A Jeremy Bowers id=67318 membership_id=48Z55

  • Now checking the driver_license table to find which one has the corresponding plate car
1
2
3
4
5
select drivers_license.id, plate_number, car_make, car_model, person.name from drivers_license
inner join person
on person.license_id=drivers_license.id
where person.id=28819 or person.id=67318;
--no need to add `and plate_number like "%H42W%"` because only 2 suspects
idplate_numbercar_makecar_modelname
4233270H42W2ChevroletSpark LSJeremy Bowers

Only Jeremy Bowers left as a suspect. It seems Joe Germuska doesn’t owns a car. plate number="0H42W2" | car make="Chevrolet" | car_model="Spark LS"

  • Let’s check the annual income of our suspect annual income=$10500 Hard to guess the motive! Seems not a killer for hire. May be police already interviewed him.

  • Let’s check our suspect

1
2
insert into solution VALUES (1, 'Jeremy Bowers');
select value from solution
1
Congrats, you found the murderer! But wait, there's more... If you think you're up for a challenge, try querying the interview transcript of the murderer to find the real villain behind this crime. If you feel especially confident in your SQL skills, try to complete this final step with no more than 2 queries. Use this same INSERT statement with your new suspect to check your answer.
  • The police interview
1
select transcript from interview where person_id=67318;
1
2
3
# Tanscript

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.

mybad! Killer for hire!

  • Hired by a woman with a lot money
  • Around 5’5”(65”) and 5’7”(67”)
  • Red hair
  • Drive TeslaModel S
  • Attended “SQL Symphony Concert” 3 times in December 2017

Finding the woman

1
2
3
4
5
select * from drivers_license
where hair_color="red"
and height between 65 and 67
and car_make="Tesla"
and car_model="Model S";

We got three suspects based on the hair color, the height and the car.

idageheighteye_colorhair_colorgenderplate_numbercar_makecar_model
2022986866greenredfemale500123TeslaModel S
2911826566blueredfemale08CM64TeslaModel S
9187734865blackredfemale917UU3TeslaModel S
1
2
3
4
5
6
7
8
9
10
11
select person.id, person.name, person.address_street_name, income.annual_income, facebook_event_checkin.event_name, count(*) from person
inner join drivers_license on person.license_id=drivers_license.id
inner join income on person.ssn=income.ssn
INNER join facebook_event_checkin on person.id=facebook_event_checkin.person_id
where drivers_license.hair_color="red"
and drivers_license.height between 65 and 67
and drivers_license.car_make="Tesla"
and drivers_license.car_model="Model S"
and facebook_event_checkin.event_name="SQL Symphony Concert"
and facebook_event_checkin.date between 20171201 and 20171231
group by facebook_event_checkin.event_name;
idnameaddress_street_nameannual_incomeevent_namecount(*)
99716Miranda PriestlyGolden Ave310000SQL Symphony Concert3

It seems the red haired woman is Miranda Priestly.

The truth

1
2
insert into solution VALUES (1, 'Miranda Priestly');
select value from solution
1
Congrats, you found the brains behind the murder! Everyone in SQL City hails you as the greatest SQL detective of all time. Time to break out the champagne!

Comments

This post is licensed under CC BY 4.0 by the author.