【データベース】素数を使った中間テーブルの削減について

こんにちは最近いろいろあって落ち込んでいるんですが、久々に更新しようと思って記事つくります。

今回はデータベースを使うときに多対多の関係性があるときに、普通は中間テーブルを作るとも思います。しかし、一方の数が少ないときにわざわざ中間テーブルつくるのめんどいなーって思っていたことがありました。

そこで素数を使ってその組み合わせで管理すれば中間テーブル省けるじゃんって思ったのがきっかけです。

まあ実用性はあまりないかもしれませんが、メモがてか記事にしたいと思います。

多対多の中間テーブル

例えば、ユーザー情報(ユーザー名や年齢、メールアドレスなど)がまとめられているユーザーテーブルがあったとします。そこに趣味の列を増やしたいとします。趣味はいろいろあると思います(音楽、ゲーム、スポーツ)。さらに1ユーザーに対して趣味はいくつあるかわかりません。

こういった場合は以下の図のようにユーザーテーブルとは別に趣味テーブルを作成して、その間に中間テーブルとして、ユーザー-趣味テーブルを作成することで、ユーザーと趣味の関係を表します。

このようにすれば、ユーザーが増えても、趣味が増えてもユーザー-趣味テーブルをみることで、どのユーザーがどの趣味を持っているかがわかります。

素数を使った中間テーブルの削減

普通は上記のようにすると思いますが、なんか中間テーブル作るのめんどくさいなーって思って考えたのが次の方法です。

先に以下に図を示します。

趣味テーブルに項目ごとに素数を割りあてます。そして、ユーザーテーブルのhobby列に当てはまる素数の掛け算の計算結果を保存するといったものです。

素数は1かその数でしか割りきれないので、ユーザーテーブルから趣味テーブルを参照するときには、各素数で割ってみて、割り切れた素数に該当する趣味がそのユーザーの趣味ということになります。例えば以下のようになります。

ただ、注意点としては大量の素数の掛け算を行うと結果が以下のように莫大になってしまいます。

素数選択肢数掛け算の最大値の計算結果
212
326
5330
74210
1152310
13630030
177510510
1989699690
239223092870
29106469693230
3111200560490130
37127420738134810
4113304250263527210
431413082761331670030
4715614889782588491410
53163.258915847719E+19

MySQLだとINTの符号なしの最大値が4294967295なので、選択肢の上限は9、BIGINTの符号なしの場合でも、最大値が18446744073709551615なので、選択肢の上限は15個がMAXです。

なので正直あんまり選択肢が増える場合はそもそも使えないですね。

実装

ローカルの環境でXAMPPを使って、MySQLとPHPとHTMLで簡易なページを作成したので、紹介したいと思います。

ユーザーテーブルは以下の感じで作りました。ユーザーIDと素数の掛け算結果を保存するprime列だけです。趣味テーブルの方はめんどくさかったので今回はユーザーテーブルだけ作って、趣味は配列としてPHPで管理することにしました。

ページは以下のような感じです。

趣味を選択して右側の送信ボタンをクリックすると、ユーザーテーブルに素数の計算結果が保存されます。簡単のためユーザーIDは自動でAutoIncrementで割り当てられるようにしています。

上記のように温泉とボードゲームを選択すると、それぞれの素数は5と7なので、かけた結果の35がPOST送信されて、prime列に保存されます。以下のような感じです。以下の例ではユーザーID9に35と保存されています。

ユーザーテーブルから趣味を抽出するにはユーザーIDのInput要素からユーザーIDを入力して送信ボタンをクリックします。これにはGET送信を使っています。そしてユーザーテーブルから該当するユーザーIDがあれば、そのprime列の値が抽出されます。そしてその値を各素数で割り算することで、該当する趣味を検索します。

以下の例は、さきほど保存したユーザーID9を入力し送信したものです。左上に温泉とボードゲームが表示されていることがわかります。

以下に全コードをのせておきますね。需要ないか。。。

まとめ

使い道があるかわかりませんが、素数で中間テーブルを削減する方法を考えてみました。

もっと効率いい方法があるかもしれませんが、使える選択肢の数も限られてますし、まあどうでもいいですかね。

参考サイト

コメント

タイトルとURLをコピーしました