仕事でSQLを叩いていると、データベースって設計からそれを扱うSQLスクリプトって、一筋縄ではいかない事がたまにあります。
単に保存されているデータを呼び出す程度にしかSQLを理解できていない人は、IO負荷値やら複雑なリレーションなどをまだ経験したことが無いから、入口に立っている状態なんでしょうね。
でも、このSQLの深層を探っていると、なかなかのパズルゲームのようでもあって、面白みもたくさんあります。
今回は先日、仕事でプログラミングしていた時に、ちょっと躓いた処理があり、
たくさんのレコード登録されているデータ群があって、それらのレコードはグループによって階層管理されています。
これらのデータ検索のシステムを作っているときの要望で、「特定の文字列があるグループを除隊して欲しい」というのがありました。
SQLでこの仕様に対応するための思考をブログに残しておきたいと思います。
サンプルデータ
仕事で使っていたデータなので、リアルデータを書くわけにはいけません。
サンプルを作ってみたのでこちらで説明します。
アカウント登録データ
Table : Account
# |
都道府県 |
名前 |
登録日 |
1 |
東京都 |
勝部 |
2024-01-01 |
2 |
東京都 |
小室 |
2024-01-02 |
3 |
東京都 |
唐沢 |
2024-01-03 |
4 |
神奈川県 |
神崎 |
2024-01-04 |
5 |
神奈川県 |
小寺 |
2024-01-05 |
これらのデータから、元日の登録者を含むグループ(都道府県)を除外するというオーダーだと考えてください。
SELECT文の考え方
単純に、元日を除外したい場合は、次のように書くだけで簡単にできます。
SELECT * FROM Account WHERE 登録日 NOT LIKE "%-01-01%"
でも、この情報からグループごと除外しなければいけません。
慣れている人であれば、サブクエリを使って出来ることがわかると思いますが、
最終的に出来上がったSELECT文は次のとおりです。
SELECT *
FROM Account
WHERE 都道府県 NOT IN (
SELECT 都道府県 FROM Account WHERE 登録日 LIKE "%-01-01%"
)
コレ!
解説
簡単に説明すると、一度除外したい対象を検索してそのグループ名(都道府県)一覧を作成します。
それをサブクエリとして、グループ(都道府県)が含まれていない事を判定するために、NOT INを使って除外します。
もちろん、このコードには注意点があり、どでかいビッグデータでやる場合は、INDEX処理をしている必要があるとか、もっと細かにWHEREで絞り込みを行わないと、スピードが遅くて使い物にならない可能性もあります。
また、LIKEを=(イコール)で判定出来たほうがより処理は早くなると思うので、データベース設計を対応出来るようにしておくことも重要ですね。
あとがき
SQLは、処理負荷を考えながら作る必要があるんですが、自主学習しようとしても、なかなか大きなデータを用意することができず、仕事でのぶっつけ本番になることが多いので、
その都度今回のようにベストプラクティスを自分で見つけていかなければいけません。
でも、これがまた、楽しいんだな。
これはエンジニアの人がみんな感じるワクワク感だと思うので、まだこのワクワクが無くて、ぶっつけ本番がしんどいと感じる人は、大きな壁を乗り越える必要があるかもしれませんね。
0 件のコメント:
コメントを投稿