コンピューターサイエンス入門:理論編
キーで join (map 利用)
この回でやること
注文とユーザーをキーで結び付ける流れを読み解き、対応表と注文の並びを確かめます。
- 読む 約 7 分
- 最後にクイズ 1 問
注文のデータに、名前は書かれていない
注文1件ごとに持っているのは user_id という番号だけで、名前は入っていません。現在の名前を注文にも書き写すと、改名したときに過去の注文まで直す必要が生まれます。名前はユーザー一覧に置き、注文側は番号でそこを指します。別の表の行を指すこの番号が外部キーです。
現在の名前を表示するなら、1か所に置くと更新漏れを減らせます。一方、注文当時の宛名を残すなら、当時の情報を別に保存する設計もあります。何の名前を見せたいかで、持ち方を決めます。
画面に現在の名前を出すには、注文の番号とユーザー一覧の番号を照合します。このようにキーでデータを結び付ける操作を JOIN と呼びます。
毎回探すより、先に対応表を作る
注文ごとにユーザー一覧を先頭から探すと、二重ループになります。ユーザー10万人、注文100万件をすべて総当たりで比較すれば、100000 × 1000000 = 1000億回です。件数が増えると、両方の件数を掛けた分だけ重くなります。
番号から名前を引ける辞書を先に1回作れば、注文ごとに一覧を読み直す必要がありません。内線番号の対応表を用意しておくのと同じ考え方です。
Python
names = {10: "吉田", 20: "山田"}
print(names[20]) # 山田
print(names[10]) # 吉田辞書の検索は平均的には1回あたりほぼ一定の時間です。ユーザーがn人、注文がm件なら、対応表を作るn件と照合するm件で、処理する件数はn + mになります。先ほどの例なら110万件です。ただし、実際の時間にはメモリやデータの読み込みも関わります。
データベースの hash join も、片方の表から対応表を作る方法です。JOINにはほかの方法もあり、データ量や索引に合わせて選ばれます。この例ではユーザー番号は重複せず、1つの番号で1人を指すとします。
無い番号の扱いも決めておく
Pythonの辞書で無いキーを引くとエラーになり、JavaScriptの通常のオブジェクトでは未定義の値になります。退会後も注文が残る設計では、名前を「退会済み」と表示するか、表示対象から外すかなどを決めます。外部キー制約が有効なら、存在しない番号を保存する段階で拒める場合もあります。
例題で確かめる
ユーザー10は吉田、20は山田です。注文を次の順に読み、番号で名前を引きます。
| 注文番号 | ユーザー番号 | 金額 | 引いた名前 |
|---|---|---|---|
| 103 | 20 | 1200円 | 山田 |
| 104 | 10 | 800円 | 吉田 |
| 105 | 20 | 500円 | 山田 |
結果の順番は注文の順のままです。山田の注文は1200 + 500 = 1700円になります。ユーザー一覧の並びで注文を並べ替えず、同じユーザーの複数の注文も残します。