質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Q&A

解決済

7回答

15351閲覧

MySQL、フラグだけの列ってどうなのでしょうか?

退会済みユーザー

退会済みユーザー

総合スコア0

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

0グッド

1クリップ

投稿2015/08/01 13:06

MySQLであるテーブルにフラグのカラムを複数追加しようと思いました。
型はBOOLEANです。

例として以下のようなカラムのテーブルだとします。
ID, flag1, flag2, flag3, flag4, flag5, flag6

CREATE TABLE tb ( ID INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, flag1 BOOLEAN, flag2 BOOLEAN, flag3 BOOLEAN, flag4 BOOLEAN, flag5 BOOLEAN, flag6 BOOLEAN, ) ENGINE=InnoDB CHARSET=utf8;

しかし上記のようにフラグだけの列がいくつもというのはどうなのかと思います。

そこでどのような方法がよいのでしょうか?

  1. 正規化してそもそもtrueとなる行だけ存在するようにする
  2. 上記のようにそれぞれおフラグのカラムを持つ
  3. ビットフラグを使う

個人的に3のビットフラグに興味があるのですが、なかなか理解するのが難しいです。
何かアドバイスをいただけたらと思います。

どうぞよろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答7

0

ベストアンサー

本題とはそれますが、どんな物かということであれば
参考ページ ビット演算 ビットフラグ
flag1 = 1 //00000001
flag2 = 2 //00000010
flag3 = 4 //00000100
flag4 = 8 //00001000
flag5 = 16 //00010000
flag6 = 32 //00100000
のように決めておいて、
・記録時はflag2とflag6がonのレコードには2+8の10を記録します //00001010
・flag4がonのレコードを得たければ、8とのビットANDを行って0で無いか調べます

SQL

1select * from tb where (flags & 8) > 0 2

・flag1とflag6の両方がonのレコードを得たければ合計値とビットANDを行って同じかを調べます

SQL

1select * from tb where (flags & (1+32)) = 33 2

・flag1かflag6の片方がonのレコードを得たければ合計値とビットANDを行って0で無いか調べます

SQL

1select * from tb where (flags & (1+32)) > 0 2

・flag1,flag2,flag4がonで他は全てoffのレコードを得たければ合計値と一致するかを調べます

SQL

1select * from tb where flags = 11 2

ビットANDは演算する両値で共にonのビットのみをonにし他は全てoffにするため、これらような事が可能です。

###長所:
・複数flagのANDやORの比較が一度に行える
・フラグ記録セルが少なくて済む

###短所:
・どの数字がどのフラグか一目でわからない。
・データを見ても何がonで何がoffかを把握するのが大変
・何本までが有効なフラグで、それぞれどのような意味かDBを覗いてもわからない
・設計書も工夫しないとどのフラグが何の意味なのかわからなくなる。
・コードの可読性が低い
※コード上だけでフラグの意味や値を変更して、設計書の編集を放置したりしたら目もあてられません。
※(flags & 51)この比較はどのフラグについて調べているのかぱっと分かりません。
※※定数化しておいて(flags & flag1+flag2+flag4+flag5)のように使うのですが……
※またビットフラグを使用したシステムと把握していないと、いきなりコードだけ見ても何をしているのかわかり難いです。

###その他
・int4で管理すると31本まで(32?)のように1セルで管理できるflag数に限界があり増やしたくなると困る。
・データ量はboolのflagが6本なら6bit(?)だが、int4が一つで32bit。
※ただし管理ビットなどを考慮すると結果的にbitflagの方が少ない気がします。
※ただいずれにしても微差ですね。

###最後に
実際混乱するだけなので推奨しません。
よほど多数のフラグを扱うなら便利ですが、まずはそのシステム設計を見直すべきです。
ゲームプログラムでキャラの状況把握に使われる事があるみたいです。

投稿2015/08/01 20:43

hirohiro

総合スコア2068

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/08/02 00:46

ありがとうございます。 非常に的確でとてもわかりやすいご説明に感謝します! そして短所が多く、ビットフラグはオススメではないのですね。 >まずはそのシステム設計を見直すべきです。 Web側でユーザーが様々な設定のチェックボックスにチェックしたり外したりしますが、その値を保存するためのカラムとしてflag1~6まで用意しました。今後このチェックボックスが増える可能性はあります。 そこでシステム設計を見直すとありますが、実際にはカラムをこのようなチェックボックス的な使い方はしないのでしょうか?もし他に方法があるのでしたらお教え頂きたいと思います。
hirohiro

2015/08/02 01:07 編集

本当に必要な設定項目なら仕方ないですし6つは多いとも思いませんので、他の方もおっしゃられるように掲示された設計で問題ないと思います。 見直すべきとしたのは設定項目が20,30と増えてきた時で、本当にそんな多数の項目が必要なのか?細かく設定できるのは本当に良いことなのか?といった方(データの持ち方ではなく)を見直したほうが良いかも知れないという事です。 それでもやっぱり必要だという時はビットフラグも選択肢になるかと思います。 アンケートの回答管理など、項目が事前に定まらず運用中も増減するものなら正規化してしまうのもありだと思いますが、今回のようなケースだとやはり今のままで良いのではないかと思います。
hirohiro

2015/08/02 01:14

あ、推奨しませんというのは、その方法こそ最良だという状況で無いなら(特に今回のようなものなら)避けたほうが良いというだけで、何が何でも選択すべきでは無いと言う訳ではありません。 他を圧倒する優れた方法なら広く利用されているはずですし、まったく過去の概念なら強く非推奨になるはずです。ニッチであっても有用な状況は有るということですね。
退会済みユーザー

退会済みユーザー

2015/08/04 09:25

再度のご回答ありがとうございます。 非常に参考になりました。 今回はこのままで行こうと思います。
guest

0

全部で7フィールド程度ならこのままでいいと思います。最適化はもちろん大切ですが、デバッグのしやすさや拡張性、メンテナンス性も考慮した方がいいかと思います。

投稿2015/08/01 13:16

rik

総合スコア1151

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/08/01 14:44

ありがとうございます。 そうですね、メンテナンス性も考えるとこのような列って確認しやすいんですよね…。 データとしては勿体無くは見えますけど…。 参考にさせて頂きたいと思います!
rik

2015/08/01 16:21

一応 & | ~ << >> などのbit演算はMySQLに有りますので、数が多いならビットで保持するのも有りですね。どれだけディスク容量の節約になるかですけど、今時、よほど容量を節約したいという意図が無い限りは使用用途によってでしょうか。 アクセス権限などUNIX的な rwx-wrx-wrx の保持や、IPアドレスの保持など2進数に換算して考えることの多いデータであれば、それも用途によってはいいかも知れません。
退会済みユーザー

退会済みユーザー

2015/08/02 00:48 編集

ありがとうございます。 たしかにディスク容量的な節約は考慮しなくてもいいレベルですね…。 そもそも、このようなチェックボックス的なフラグをカラムで持つということ自体、データベース設計において正規化してないし無駄と思われそうで質問させて頂きました。 私は仕事でデータベースを扱っているわけではないので(勉強の段階です)、他の人が私のデータベース設計を見ることはないのですが、実際に事業プロジェクトとしてプロの方々が設計する場合、このようなチェックボックス的なカラムはアリなのでしょうか?
rik

2015/08/02 01:24

booleanフィールドはよく使います。ディスク容量の心配よりは応答速度の心配をしますし、やはりメンテナンス性、拡張性ですね。それと忘れたころや他人がプログラムコードを見たときに直感的に理解できるか、誤認することは無いか、などの方が重要です。
退会済みユーザー

退会済みユーザー

2015/08/02 01:36

ありがとうございました。 アドバイスいただいてとてもすっきりしました。
rik

2015/08/03 00:07

katoyさんのコメントを見て思い出しましたが、カンマ区切り文字列で登録するという方法もよく使います。それぞれのフラグが a c f h k m という頭文字だったとすると、 "a,h" "a,c,f,k" "c,k,m" というデータになり、判別も容易で、MySQLにはカンマ区切り文字列を扱うFIND_IN_SET関数が有りますので、SELECTも容易です。 "ノート,えんびつ,消しゴム,万年筆,しおり" といった感じでも使えますし、データ数はいつでも変更可能です。
guest

0

教科書的には、フラグ用のテーブル用意したほうがよい気がします。
これだけ並ぶとフラグの増減がある気がするからです。

欠点としては、検索時に負荷がかかることが心配されます。
IOのオーバーヘッドは、送受信するデータ量の方が検索の時間より影響が
大きいので、どっちも注意が必要ですけど。

フラグ用のテーブルは”外部キー+フラグ種別”でPrimaryKeyとして、項目としてはフラグが入ります。

また、使わなくなったフラグを名称変更せずに使うと意味がカラム名から
わからなくなったりするので、気をつけたほうが良いです。

ビットテーブルも有効ですが、やはり、意味がわからなくなりやすいので
管理方法はきっちり考えたほうが良いとおもます。

投稿2015/08/02 01:24

iwamoto_takaaki

総合スコア2883

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/08/04 09:24

ありがとうございます。 フラグ用テーブルを用意するというアドバイス、参考にさせて頂きたいと思います。
guest

0

こんばんわ。
用途がチェックボックス的な役割ならば、私は日付(日時)を持たせます。
trueにした日付(日時)を記録し、falseならNULLにします。
こうすることにより、trueにした日付(日時)を記録することもできます。

結局、用途がわからないので、これもおすすめできるかどうかは分かりません…。

投稿2015/08/01 15:19

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/08/02 00:41

ありがとうございます。 そうですね、チェックボックス的な意味合いのカラムで、さらにチェックした日付が必要な場合は私もそのようにしています。 用途は、本当にチェックボックス的な用途だけなので、特に日時は必要ない状況です。
guest

0

ビットフラグのみの回答で該当かどうかわかりませんが、昔あるメーカーの商品製造工程でビットフラグを使った事があります。
ある商品を作るために複数の材料を投入するのですが、材料もほとんどが複数の商品に使われる物だった為
製品に使う材料に1~52(材料が52個あった)まで番号を付け、製品の方には使う材料の該当ビットをONしたデータを持たせました。で、投入可かどうかの判定に部品の番号に対応したビットがONならば投入できるという判断をしました。・・・そういう使い方ならビット判断でいいと思います。
逆に別々の判断をする為のフラグであればお勧めしません。

投稿2015/08/01 13:54

cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/08/01 14:50

ありがとうございます。 >投入可かどうかの判定に部品の番号に対応したビットがONならば投入できるという判断をしました。 というのは、1~52の例えば30番のビットをONにし、その他の番号はONにすることはない、ということでしょうか?例えば30番と18番をONにするなど複数のビットをONにするということはしないという感じですか? ビットフラグを実際に使ったことがないのですが、なんとなく複数のビットの判定ってどうやるんだろう?という漠然とした疑問はあります。
cateye

2015/08/01 22:24 編集

フラグの持ち方にちょっと勘違いがあったので訂正も含めて説明します。当時は今のように高速な回線やPCがなかったため、実際には製造中の商品のデータを一定時間ごとにテーブルから読み出してメモリに持っていました。そして、部品のバーコードを受信するたびにバーコードから部品を特定して、その部品がラインに投入できるかどうかをAND演算にてDBに問い合わせるという事をしていました。・・・部品も複数の商品に対応しているため実際には複数のビットが立ったフラグをもっています。そしてAND演算の結果が0以外であれば投入可という判断をしていたのです。フラグそのものは64ビット整数を使っていたと思います。
guest

0

テーブル構造だけ見せられても判断はできませんね…
どういうシステムでそのフラグがどういう意味を持っているのか、がわからないとそれが妥当なのかどうかは判断できません。

投稿2015/08/01 13:16

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/08/01 14:54 編集

ありがとうございます。 flag1~6まではチェックボックスのような役割です。 どれか一つだけtrueになるのではなく、どれでもtrue/falseになりうる感じです。 そして、以下のようなSELECTをしたりします。 SELECT ID FROM tb WHERE flag1 = 1 AND flag3 = 1 SELECT ID FROM tb WHERE flag4 = 1 OR flag6 = 1
退会済みユーザー

退会済みユーザー

2015/08/01 15:21

「どういう意味」かというのはそうじゃなくて…
退会済みユーザー

退会済みユーザー

2015/08/01 15:27

ありがとうございます。 すみません、よくわからないので無視してください…。
guest

0

一つのアイデアを述べます。(これがベストかは、状況によります)

  • 1 つのカラムだけを追加する。
  • データ・タイプは String とする。
    checkbox の on は 1, off は 0 として 文字列 "010101" のようにして 6 つの bool 値を6文字で表す事にする。
  • この列には index を張る。

select で文字列 "010101" のような文字列を指定したり、like で正規表現を指定したりして検索を行うようにします。

投稿2015/08/02 16:37

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/08/04 09:31

ありがとうございます。 実は私もそのように考えたりしました。 ですが検索時に問題が起きそうで無理な気がしました。 例えば3桁目が1である文字列ってものすごくパターンがありますよね・・・? 000100, 001100, 100100, 111100, …など。 これをどうやって検索することになるのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問