SQL-детектив: кража в коворкинге «Гараж»

Детективная игра по SQL на русском. Улики лежат в таблицах, твой инструмент — запросы: восстанови события и назови заказчика кражи. Бесплатно и без регистрации.

  • 7 шагов
  • 8 таблиц
  • 30–60 минут
  • для начинающих

Улики по порядку

найдено 0 из 7

Шаг 1 из 7

  1. Заявление о краже текущий шаг

    Начни с журнала происшествий: за неделю в нём несколько записей, и только одна о краже. Найди её и узнай, из какой комнаты пропал прототип.

    к SQL-запросу

    нужно: SELECT и WHERE

    подсказка

    Столбец kind хранит тип происшествия одним словом в нижнем регистре.

    ещё подсказка: заготовка запроса

    Заполни пропуски ___ значениями из задания и выполни запрос.

    SELECT room, reported_at, description
    FROM incidents
    WHERE kind = '___';

  2. Кто слышал служебный выход закрыт

    Утром охрана сняла двенадцать показаний. Кто-то из опрошенных упомянул служебный выход: найди это показание по тексту и назови человека.

    к SQL-запросу

    нужно: LIKEJOIN

    подсказка

    Текст лежит в statements.statement, имена в people.full_name. Ищи подстроку «служебный выход» через LIKE.

    ещё подсказка: заготовка запроса

    Заполни пропуски ___ значениями из задания и выполни запрос.

    SELECT p.full_name, s.statement
    FROM statements s
    JOIN people p ON p.id = s.___
    WHERE s.statement LIKE '%___%';

  3. Кто вышел через служебный выход закрыт

    Проверь слова охранника по журналу турникетов: сколько разных людей вышли через служебный выход 13 марта между 23:30 и 23:50?

    к SQL-запросу

    нужно: BETWEEN и датыCOUNT(DISTINCT)

    подсказка

    Дата и время в passed_at, сравнивай со строкой вида '2026-03-13 23:30'. Считай DISTINCT person_id, чтобы двойной проход не удвоил ответ.

    ещё подсказка: заготовка запроса

    Заполни пропуски ___ значениями из задания и выполни запрос.

    SELECT COUNT(DISTINCT person_id)
    FROM access_log
    WHERE door = '___'
      AND direction = '___'
      AND passed_at BETWEEN '2026-03-13 ___' AND '2026-03-13 ___';

  4. Кто из них был на третьем этаже закрыт

    У каждого этажа своя точка Wi-Fi. Кто из этих двоих был подключён к сети третьего этажа между 22:30 и 23:40?

    к SQL-запросу

    нужно: подзапрос и INJOIN

    подсказка

    Сессия пересекает окно, если началась до его конца и закончилась после его начала: started_at < '…23:40' AND ended_at > '…22:30'. Двоих с прошлого шага подставь подзапросом.

    ещё подсказка: заготовка запроса

    Заполни пропуски ___ значениями из задания и выполни запрос.

    SELECT p.full_name, w.started_at, w.ended_at
    FROM wifi_sessions w
    JOIN people p ON p.id = w.person_id
    WHERE w.floor = ___
      AND w.started_at < '2026-03-13 ___'
      AND w.ended_at > '2026-03-13 ___'
      AND w.person_id IN (
        -- условие из шага 3
        SELECT person_id
        FROM access_log
        WHERE ___
      );

  5. Машина у шлагбаума закрыт

    Подозреваемый вышел в 23:41. Какая машина покинула паркинг в следующие десять минут?

    к SQL-запросу

    нужно: interval и даты

    подсказка

    Верхняя граница: '2026-03-13 23:41'::timestamp + interval '10 minutes'. Или запиши обе границы строками.

    ещё подсказка: заготовка запроса

    Заполни пропуски ___ значениями из задания и выполни запрос.

    SELECT plate, person_id, left_at
    FROM parking
    WHERE left_at BETWEEN '2026-03-13 ___'
      AND '2026-03-13 ___'::timestamp + interval '___';

  6. Чья это машина закрыт

    Номер есть, теперь владелец и его компания: соедини паркинг с людьми и компаниями и назови компанию.

    к SQL-запросу

    нужно: JOIN трёх таблиц

    подсказка

    parking.person_id ведёт в people.id, а people.company_id в companies.id. Машина заезжала всю неделю, поэтому без DISTINCT получишь одну строку на каждый заезд.

    ещё подсказка: заготовка запроса

    Заполни пропуски ___ значениями из задания и выполни запрос.

    SELECT DISTINCT c.name, p.full_name
    FROM parking pk
    JOIN people p ON p.id = pk.___
    JOIN companies c ON c.id = p.___
    WHERE pk.plate = '___';

  7. Заказчик закрыт

    Кражу готовили заранее: кто-то из компании владельца машины всю неделю с 9 по 13 марта бронировал переговорные третьего этажа. Кто из этой компании делал это чаще всех?

    к SQL-запросу

    нужно: GROUP BY и COUNTORDER BY и LIMIT

    подсказка

    Переговорные третьего этажа начинаются с «3-»: room LIKE '3-%'. Сгруппируй по человеку и отсортируй по COUNT(*) DESC.

    ещё подсказка: заготовка запроса

    Заполни пропуски ___ значениями из задания и выполни запрос.

    SELECT p.full_name, COUNT(*) AS bookings
    FROM bookings b
    JOIN people p ON p.id = b.person_id
    JOIN companies c ON c.id = p.company_id
    WHERE c.name = '___'
      AND b.room LIKE '___'
      AND b.starts_at >= '2026-03-09' AND b.starts_at < '2026-03-14'
    GROUP BY ___
    ORDER BY bookings DESC
    LIMIT 1;

Прогресс и запрос сохраняются в этом браузере.

SQL-консоль

PostgreSQL в браузере только чтение
осмотреться:
Ctrl / ⌘ + Enter

Пиши SELECT: результат появится ниже. База восстанавливается перед каждым запуском.

Выполни первый запрос, чтобы осмотреть материалы дела. При первом запуске загрузится PostgreSQL — около 17 МБ.

к заданию ↑
таблицы и связи 8
Схема связей таблиц people.company_id ведёт в companies; incidents.reported_by ведёт в people; statements.person_id ведёт в people; access_log.person_id ведёт в people; wifi_sessions.person_id ведёт в people; bookings.person_id ведёт в people; parking.person_id ведёт в people; people.host_id ведёт в people companies incidents wifi_sessions statements people bookings access_log parking company_idreported_byperson_idperson_idperson_idperson_idperson_idhost_id
people.id связан с person_id, reported_by и host_id. Компания человека: people.company_id → companies.id.

Нажми на имя таблицы, чтобы подставить запрос.

  • 11 строк компании-резиденты и их офисы id, name, floor, room
  • 57 строк все, у кого есть бейдж; у гостя host_id указывает на пригласившего id, full_name, role, company_id, host_id
  • 7 строк журнал происшествий охраны id, reported_at, reported_by, room, kind, description
  • 12 строк показания, снятые утром 14 марта id, person_id, taken_at, statement
  • 472 строки турникеты: главный вход, паркинг, служебный выход id, person_id, door, direction, passed_at
  • 213 строк подключения к точкам доступа, по одной на этаж id, person_id, floor, started_at, ended_at
  • 63 строки брони переговорных id, room, person_id, starts_at, ends_at, purpose
  • 68 строк шлагбаум паркинга id, plate, person_id, entered_at, left_at

Как играть

  1. Читай шаг и пиши запрос в консоли. Результат появляется под редактором.
  2. Впиши найденное в поле ответа. Регистр, «ё» и кавычки не важны.
  3. Верный ответ открывает следующий шаг и один из рабочих запросов, чтобы сравнить со своим.

Прогресс и последний запрос хранятся в этом браузере. Кнопка «начать заново» — над шагами расследования.

Вопросы об игре

Это как SQL Murder Mystery, только на русском?

Да, жанр тот же: преступление спрятано в базе данных, и раскрыть его можно только запросами. Оригинальные SQL Murder Mystery и SQL Noir написаны на английском. Здесь на русском всё: сюжет, показания, подсказки. База работает на PostgreSQL прямо во вкладке браузера.

Нужно знать SQL, чтобы начать?

Хватит SELECT и WHERE: первую улику находит запрос в одну строку, а кнопки «осмотреться» подставляют готовые. JOIN, подзапрос и GROUP BY понадобятся дальше. К каждому шагу есть подсказка и ссылка на разбор конструкции в справочнике.

Сколько длится игра?

Семь шагов, на всё уходит 30–60 минут. Найденные улики и последний запрос сохраняются в этом браузере: можно закрыть вкладку и вернуться к делу позже. После первого дела ждёт второе, для продолжающих.

Что тренируешь

Каждая конструкция разобрана в справочнике: ссылка ведёт на статью с примерами на живой базе.

Дальше

Преподавателям

Урок на 45 минут

  1. 5 минут Раздай ссылку и прочитайте досье вслух: в нём время, место и кто что видел.
  2. 20 минут Шаги 1–3: WHERE, LIKE с первым JOIN, BETWEEN по времени и COUNT(DISTINCT).
  3. 15 минут Шаги 4–7: подзапрос с IN, interval, JOIN трёх таблиц, GROUP BY с сортировкой.
  4. 5 минут Разбор: после верного ответа открывается эталонный запрос, сравните его с запросами учеников.
  • Регистрация не нужна: прогресс хранится в браузере ученика. На общих компьютерах в конце занятия нажми «начать заново».
  • Ответы проверяются сразу и не лежат на странице открытым текстом, проверять вручную ничего не нужно.
  • Сильной группе дай дело № 02: оно для продолжающих.

Ссылка на эту страницу в материалах курса приветствуется. Диалект PostgreSQL, данные вымышлены, совпадения случайны.

Что тренирует каждый шаг

ШагКонструкции
1. Заявление о кражеSELECT и WHERE
2. Кто слышал служебный выходLIKE, JOIN
3. Кто вышел через служебный выходBETWEEN и даты, COUNT(DISTINCT)
4. Кто из них был на третьем этажеподзапрос и IN, JOIN
5. Машина у шлагбаумаinterval и даты
6. Чья это машинаJOIN трёх таблиц
7. ЗаказчикGROUP BY и COUNT, ORDER BY и LIMIT