Ghost in the SQL Data はどんなゲーム? 本物のSQLを書いて、記録の山から手がかりを探す捜査ゲーム
このゲームでは、警察署の机に置かれた1年分の通報記録を、自分で書いたSQLで調べます。記録は2,400件。その中から、学校が燃える14分前に電話をかけた人を探し出すのが、最初の事件です。
書くのは数行のSQLです。日付で絞り、別の表と突き合わせ、時刻の順に並べると、2,400件が1人まで減っていきます。その減り方が楽しく、体験版を遊んでハマりました。この記事では、体験版で遊べる全部の事件について、考え方と答えになるSQLを紹介します。答えはネタバレにならないように折りたたんでいます。
- 体験版で遊べるのは、入門の3つ(Ashgrove火災の1〜3)と、単発事件の2つ(青い家、Orsayの王冠)。事件ごとに出される問題が「チェックポイント」で、全部で11問
- 答えは、SQLを実行した結果の行で出す。「検証」を押すと、その行が調べられる
- 使うのは、WHERE、JOIN、ORDER BY、LIMIT、BETWEEN などの基本の句だけ。SQLを書いたことがなくても、入門から順に進められる
- 詰まったら、ヒントを段階的に開ける。最後の段が答えそのもの
- SQLに書く値は英語のまま。’Phone Call’ のように、表のとおりに書く
体験版をもとに書いています。製品版は2026年10月29日発売予定です。事件の答えは、ネタバレにならないように折りたたみの中に入れています。

価格および配送状況は変更される場合があります。購入時は商品ページをご確認ください。
1. 画面と遊び方
最初に、ゲームモードを選びます。「チュートリアル」はSQLを学ぶ場、「単発事件」は練習する場です。単発事件は6件の事件ファイルが並び、体験版で開けるのは青い家とOrsayの王冠の2つです。残りの4つは「近日公開」と出ます。「読者の事件」は製品版で遊べます。

入門は「机」の画面で遊びます。左に事件の資料があり、「求める結果」、求められる結果の形を示した見本、「検証」ボタンが並びます。右にSQLを書く欄と実行ボタン、その下に結果の表が出ます。クエリはタブで増やせます。結果は表で出ますが、棒グラフ、折れ線グラフ、円グラフ、KPIにも切り替えられます。2,400行を出しても、表示されるのは先頭の400行です。 使えるのは、読むだけの SELECT と WITH です。書き換える命令は使えないので、何を入力しても事件の記録は壊れません。
事件は、選択画面から順に開きます。入門の3つは、前の答えが次の質問になる1本の話です。解いた事件には、出した答えが表示されます。
単発事件は「捜査ボード」の画面です。写真、書類、付箋、事件で使う表の中身の抜粋がボードに並びます。ボードは画面より広く、Spaceキーを押しながらドラッグして動かします。「事件資料」と「白いパネル」のボタンで、左右のパネルを出したり隠したりします。事件資料のパネルに問題と「検証」ボタンがあり、白いパネルがSQLを書く場所です。検証を通したクエリは、自動でボードに留められます。

2. 体験版の事件一覧
| 事件 | 難易度 | 使う表 | チェックポイント | 使う句 |
|---|---|---|---|---|
| 入門(Ashgrove火災 1) | 初級 | dispatch_log | 3 | SELECT、WHERE、AND |
| 結合(Ashgrove火災 2) | 初級 | line_register、dispatch_log | 3 | JOIN |
| ORDER BY(Ashgrove火災 3) | 初級 | keycard_log | 2 | ORDER BY、LIMIT |
| 青い家 | 初級 | shop_sales、loyalty_cards | 1 | JOIN、WHERE |
| Orsayの王冠 | 中級 | badge_passages、badge_holders、museum_rooms | 2 | JOIN、BETWEEN |
表の大きさは、dispatch_log が2,400行、badge_passages が2,633行、shop_sales が1,240行です。ほかの表は、10行から260行です。
3. 先に覚えるルール3つ
ルール1: 答えは結果の行で出す
検証は、実行した結果の行を見ます。各チェックポイントの「求める結果」に、行数や列の形が書いてあります。16行、1行のように、実行のたびに数が合っているかをSQLで確認します。 人物を求められる事件では、その人の行を、持ち主の一覧の表から出します。たとえば会員カードの表なら、名前で絞って次のように書きます。
SELECT * FROM loyalty_cards WHERE holder = 'Karen Walsh';ルール2: 条件の言葉は、資料の中にある
日付、時刻、部屋の名前、ブランド、バッジの番号。事件の資料に出てくる言葉が、そのまま WHERE の値になります。 値は英語のまま、シングルクォートで囲み、大文字と小文字も表のとおりに書きます。’Phone Call’、’Blue Paint’ のようにです。時刻は ’21:12′ と書き、< や > で前後を比べます。
ルール3: 全体を見てから、1つずつ絞る
最初は SELECT * で表を全部出します。次に日付、次に場所と、条件を1つ足すたびに件数を見ます。2,400件、16件、1件のように減れば、絞り込みが合っています。減り方が資料の説明と合わないときは、条件のどれかが違います。
4. 事件ごとのSQL(ネタバレ)
折りたたみの外には、導入と使う句だけを書いています。自分で解きたい人は、折りたたみを開かずに先へ進んでください。
4-1. 入門(Ashgrove火災 1)
10月14日の夜、Ashgrove中学の理科棟が燃えました。表は dispatch_log だけで、列は id、on_date、at_time、district、site、subject、kind、source の8つです。求めるのは、最初の目撃者が炎を見た21:12より前に、学校の火災を通報した1件です。
答えとSQLを見る(ネタバレ)
チェックポイント1は、表を全部出します。2,400行です。
SELECT * FROM dispatch_log;
チェックポイント2は、火災の日で絞ります。16行です。
SELECT * FROM dispatch_log WHERE on_date = '2026-10-14';
チェックポイント3は、通報の種類と場所と時刻を足します。1行で、20:58、発信元は LINE 4417 です。
SELECT * FROM dispatch_log
WHERE on_date = '2026-10-14'
AND kind = 'Phone Call'
AND site = 'Ashgrove Middle School'
AND at_time < '21:12';
場所を書き忘れると、1行になりません。火災(subject が Fire)で21:12より前の記録を出すと、Rialto Cinema の19:32が混ざって2行になります。
SELECT at_time, site, source FROM dispatch_log
WHERE on_date = '2026-10-14' AND subject = 'Fire' AND at_time < '21:12';
その日の学校の記録は11件です。20:58の1件だけが、21:12より前にあります。
4-2. 結合(Ashgrove火災 2)
20:58の通報は、LINE 4417 からの連絡です。電話会社の台帳 line_register に、回線ごとの契約者と部屋があります。列は line、subscriber、room、hours、address、district の6つで、30行です。チェックポイント1を解くと、dispatch_log が開きます。dispatch_log の source と、line_register の line が同じ値です。求めるのは、通報が学校のどの部屋から連絡が来たかです。
答えとSQLを見る(ネタバレ)
チェックポイント1は、台帳の2列を出します。30行です。
SELECT line, subscriber FROM line_register;
チェックポイント2は、2つの表を JOIN でつなぎます。8行です。
SELECT at_time, source, room, hours
FROM dispatch_log
JOIN line_register ON source = line
WHERE on_date = '2026-10-14';
その日の通報は16件でしたが、結果は8行です。台帳にない発信元の行は、JOIN で消えます。目撃の報告、公衆電話、警報盤、パトカー、救急車などです。 20:58の通報だけは、2行になります。LINE 4417 は2つの部屋で登録されているからです。
SELECT room, hours FROM line_register WHERE line = 'LINE 4417';
Main Office が 08:00-18:00、Lodge が 18:00-08:00 です。20:58は夜の時間帯なので、Lodge です。
チェックポイント3は、時間帯で1行に絞ります。
SELECT room, at_time
FROM dispatch_log
JOIN line_register ON source = line
WHERE source = 'LINE 4417'
AND on_date = '2026-10-14'
AND hours = '18:00-08:00';

4-3. ORDER BY(Ashgrove火災 3)
Lodge は用務員の部屋です。学校には、バッジの記録 keycard_log があります。列は badge、holder、role、door、on_date、at_time の6つで、10月12日から16日までの182行です。求めるのは、その日に最後に正門から出た人と、20:58より前に最後に Lodge の扉を通った人です。
答えとSQLを見る(ネタバレ)
チェックポイント1は、正門の記録を新しい順に並べて、先頭の1行だけ取ります。Ruth Abasi の23:20です。
SELECT holder, door, at_time
FROM keycard_log
WHERE on_date = '2026-10-14' AND door = 'Main Gate'
ORDER BY at_time DESC
LIMIT 1;
チェックポイント2は、同じ形のまま、条件を Lodge と20:58より前に変えます。Victor Pell の20:44です。
SELECT holder, at_time
FROM keycard_log
WHERE door = 'Lodge' AND on_date = '2026-10-14' AND at_time < '20:58'
ORDER BY at_time DESC
LIMIT 1;
Victor Pell のその日の動きを見ると、Science Wing を20:41に通り、3分後に Lodge を通っています。
SELECT door, at_time FROM keycard_log
WHERE holder = 'Victor Pell' AND on_date = '2026-10-14'
ORDER BY at_time;

価格および配送状況は変更される場合があります。購入時は商品ページをご確認ください。
4-4. 青い家
Mill Lane の家5軒が、夜のうちに青く塗られました。生け垣に、Brikoko の Blue Paint の空き缶が1つ残されています。表は2つです。shop_sales は金物店 Brikoko の4月から6月の売上で、1,240行です。列は sale_id、on_date、at_time、item、brand、qty、price、card の8つです。loyalty_cards は会員カード260枚の持ち主と住所です。求めるのは、そのペンキを買った人の行です。
答えとSQLを見る(ネタバレ)
Blue Paint と Brikoko で絞り、カードごとに数えます。カードは1枚だけで、22回の買い物です。
SELECT card, COUNT(*) AS times
FROM shop_sales
WHERE item = 'Blue Paint' AND brand = 'Brikoko'
GROUP BY card;
そのカードの持ち主を、JOIN で出します。Miles Greaves、7 Mill Lane です。
SELECT DISTINCT loyalty_cards.card, holder, house, street
FROM shop_sales
JOIN loyalty_cards ON shop_sales.card = loyalty_cards.card
WHERE item = 'Blue Paint' AND brand = 'Brikoko';
ブランドを外すと、ほかの会社の青いペンキの買い手が混ざります。ブランドごとにカードの数を見ると、Brikoko が1枚、Dulvo が12枚、Greenway が9枚です。
SELECT brand, COUNT(DISTINCT card) AS cards
FROM shop_sales
WHERE item = 'Blue Paint' AND card <> ''
GROUP BY brand;
カードを持たずに買った客は、card が空欄になっています。JOIN ではその行が消えます。
4-5. Orsayの王冠
11月19日の18:40、Orsay美術館の収蔵庫で、式典の王冠が消えました。扉は職員用のバッジで開きます。表は3つです。badge_passages はその日のバッジの記録で、2,633行です。列は passage_id、badge_id、room、direction、at_time の5つで、direction は in と out です。badge_holders はバッジの持ち主で、224人です。museum_rooms は10の部屋と、誰でも入れるかどうかです。ボードには、1階の見取り図があります。チェックポイントは、収蔵庫を開けたバッジの持ち主と、そのバッジを盗んだ人です。

答えとSQLを見る(ネタバレ)
チェックポイント1は、王冠をしまった17:30から、空だと分かった18:40のあいだに、収蔵庫(Reserve)の記録があるバッジを探します。1人だけで、Etienne Vasseur、登録係(Registrar)のバッジ B-0218 です。
SELECT DISTINCT h.last_name, h.first_name, h.badge_id, h.role
FROM badge_passages p
JOIN badge_holders h ON h.badge_id = p.badge_id
WHERE p.room = 'Reserve' AND p.at_time > '17:30' AND p.at_time < '18:40';
Vasseur は17:30から体調を崩し、トイレにいて、上着のバッジがなくなったと話しています。チェックポイント2は、そのバッジを盗んだ人です。Vasseur は17:31に Restrooms に入っています。同じ時間に Restrooms に入った別のバッジを探します。
SELECT DISTINCT h.last_name, h.first_name, h.badge_id, h.role
FROM badge_passages p
JOIN badge_holders h ON h.badge_id = p.badge_id
WHERE p.room = 'Restrooms'
AND p.at_time BETWEEN '17:31' AND '17:38'
AND p.badge_id <> 'B-0218';
答えは Hugo Delorme です。role は Visitor、来館者のバッジです。その日の動きを見ます。
SELECT room, direction, at_time FROM badge_passages
WHERE badge_id = 'B-0109'
ORDER BY at_time;
Restrooms に17:33に入ったあと、出た記録がありません。Restrooms を17:38に出た記録は、Vasseur のバッジです。そのバッジが17:55に収蔵庫に入り、18:01に出ています。Delorme の最後の記録は、18:10の正面入口です。

価格および配送状況は変更される場合があります。購入時は商品ページをご確認ください。
5. コツ1〜4
コツ1: JOIN で行が消えたら、片方の表にしかない値を疑う
JOIN でつなぐと、2つの表の両方に同じ値がある行だけが残ります。片方の表にしかない値の行は消えます。4-2 は、通報の記録16件のうち、発信元が台帳に載っていない8件が消えて、8行になりました。4-4 は、カードを持たずに買った客の行が消えます。件数が思ったより少ないときは、消えた行の理由を先に考えます。
コツ2: JOIN で行が増えたら、同じ値が2回ある行を疑う
つないだ先の表に、同じ値の行が2つあると、1件が2行になります。4-2 では、台帳に LINE 4417 が2回載っていたので、1件の通報が2行になりました。2行を分けている列(ここでは hours)を、WHERE に足して絞ります。
コツ3: 「直前」と「最後」は ORDER BY と LIMIT 1
最後の1人は ORDER BY at_time DESC LIMIT 1 です。「20:58より前の最後」は、at_time < ’20:58′ を足します。日付も一緒に書きます。時刻だけの条件は、別の日の記録にも当てはまります。
コツ4: 「同じ時間にいた別の人」は、BETWEEN と <> で探す
4-5 は、17:31から17:38の Restrooms にいた人を探しました。BETWEEN は両端の時刻を含みます。持ち主本人を除くには、<> で本人のバッジを外します。候補が1人になるまで、時間の幅を狭めます。
6. ヒントとSQLの手引き
ヒントは段階式です。最初は「手がかり」で、探す場所を教えます。続けて、ヒント1が言葉での説明、ヒント2が骨組みと名前、ヒント3が解答です。前の段を開かないと、次の段は「ロック中」のままです。解いたあとの一覧には、ヒントを使わなかったか、いくつ開いたかが残ります。

「SQLの手引き」は、句ごとのカードが並ぶ一覧です。例の表を使って、短い例とその結果を見られ、「やり方を見る」で1ステップずつ確かめられます。SELECT と FROM、WHERE、LIKE、AND と OR、括弧のつけ方、時刻の比べ方、BETWEEN などのカードがあります。事件の表は使わないので、答えが出ることはありません。

7. 日本語対応
メニュー、事件の資料、手引き、ヒントは日本語で出ます。最初に英語で起動したときは、設定の「言語」で日本語を選びます。表のテーブル名、列名、中身の値は英語のままで、人名と地名も英語表記です。SQLを書くときは、資料に書かれた英語をそのまま使います。対応言語は、日本語を含む9つです。 設定には、そのほか、表示(全画面)、パネルの大きさ、効果音と音楽の音量、配信者モード、SQLの間違いを強調する項目があります。
8. 基本情報
| タイトル | Ghost in the SQL Data(体験版は Ghost in the SQL Data Demo) |
| 開発 | Isaac MENARD |
| 販売 | Isaac MENARD |
| 発売日 | 2026年10月29日予定(体験版は2026年9月9日から配信) |
| 価格 | 未発表(体験版は無料) |
| 対応機種 | Windows、Mac |
| 対応言語 | 日本語を含む9言語(英語、フランス語、イタリア語、ドイツ語、スペイン語、日本語、韓国語、ロシア語、簡体字中国語) |
| ストア | 製品版(Steam)/体験版(Steam) |
価格および配送状況は変更される場合があります。購入時は商品ページをご確認ください。
まとめ
- 体験版で遊べるのは、入門の3つと、単発事件の青い家、Orsayの王冠。問題(チェックポイント)は全部で11問で、どれも数行のSQLで解ける
- 答えは、実行した結果の行で出す。件数が「求める結果」と合うかを、実行のたびに見る
- 値は英語のまま、シングルクォートで囲む。時刻は ’21:12′ のように書いて、< と > で比べる
- JOIN で行が消えたら片方の表にしかない値、増えたら同じ値が2回ある行を疑う
- 「最後」と「直前」は、ORDER BY の DESC と LIMIT 1。同じ時間にいた人は、BETWEEN で探す
- 詰まったら、手がかり、ヒント1、2、3の順に開く
誰かの何かの役に立ちますように。
2026年10月6日時点、体験版の内容です。