【システム編】バレンタイン2022のスペシャルサイトのシステムについて

ポチればきっと愛も伝わるはず。

プログラミング脳、流行っていますね!本屋さんでも子供向けから大人向けまでいっぱい本を見かけます。
さて皆さんもこの記事でプログラミング脳を鍛えよう!(キラキラ)

さてさてSQLの時間だよ

「ここになまえをいれてね」と「みてみる」の動きは難しくないですね。

「なまえ」は出力用、結果は、MySQLにある結果を ORDER BY RAND() で取得です。ORDER BY RAND() は重たい処理なので、件数が多い時は、要注意です。

特定の名前が入力された時は、結果は固定になります。これも簡単ですね! 結果と名前を同じテーブルに入れておき、WHERE で name を検索。message を取得します。こんな感じです。

SELECT message FROM テーブル名 WHERE name = 入力された名前

「入力された名前」は、もちろんそのままSQLに流さず、エスケープ処理を入れましょうね・・!(この記事では省略中)

名前なので、入力された値は「苗字氏名」「苗字 氏名」の2パターンが想定されます。
テーブルにはスペース無しの「苗字氏名」で入れて、入力された値はスペースを削除してから検索するとムラなく検索できそうです。ちなみにスペースにも半角・全角があるので、注意ですぞ・・! 入力ではなく、コピーされた文字の場合、スペースに見せかけたタブ(\t)の場合もあります。よくよく考えて対応しよう。

ここまででまとめると、「ランダムな結果」「名前に紐づいた一意な結果」の2つがあります。
「ランダムな結果テーブル」「名前に紐づいた一意な結果テーブル」の2つを用意してもよいのですが、フラグを持たせて1つのテーブルでも対応できますね。

flg が 1 の時は「名前に紐づいた一意な結果のメッセージ」、flg が 0 の時は「ランダムな結果のメッセージ」というルールを作ります。

まずは flg=1 で名前を検索します。

SELECT message FROM テーブル名 WHERE flg = 1 AND name = 入力された名前

「入力された名前」が、nameカラムに入っていれば、検索がヒットして、SQL終了です。

ヒットしなければ、続けて flg=0 で、「ランダムな結果のメッセージ」からランダムにメッセージを取得します。必要なのは結果 1 件のみなので、LIMIT 1 も忘れずに。

SELECT message FROM テーブル名 WHERE flg = 0 ORDER BY RAND() LIMIT 1;

あのポチポチは?

ポチポチは、カウントアップさせてもよかったのですが、同時接続が多いことが想定されるので、カウントアップ方法だと少々怖いです。

カウントアップ方法とは、「ポチポチ・テーブル」に入っている値が 100 であれば、101 にして再登録する方法です。

これのどこが怖いかというと、

Aさん「あ、100 カウント」 → 101 にポチ!
Bさん「あ、100 カウント」 → 101 にポチ!

同時にこれが起きた場合、101 と 102 はどうなる問題ですね・・。もちろん上手に回避する方法はたくさんあるのですが、登録に失敗すると最悪データが壊れてカウントが 0 に戻ってしまうかも・・という懸念は消えません。

なので今回はチケット方式にしました。チケット方式は、ただ単純に、接続があった時に「ポチポチ・テーブル」にレコード(行)を足すだけです。

Aさん「あ、100 カウント」 → 101 にポチ!(1レコード追加)
Bさん「あ、100 カウント」 → 101 にポチ!(1レコード追加)

カウント数を取得する時は、レコード数を集計します。

SELECT count(id) AS ID FROM ポチポチ・テーブル;

チケット方式であれば、同時接続による万が一のAさんもしくはBさんの登録エラーが起きても、1レコードが追加されないだけで、累積されたレコードには影響がないのでカウントが 0 に戻ることはありません。

プログラミングには、いろいろな解決方法がありますね。状況によって最適な方法を常に見つけていきたいですね٩(๑❛ᴗ❛๑)۶