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

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

ただいまの
回答率

90.49%

  • MySQL

    5995questions

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

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

解決済

回答 7

投稿

  • 評価
  • クリップ 0
  • VIEW 4,260
退会済みユーザー

退会済みユーザー

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のビットフラグに興味があるのですが、なかなか理解するのが難しいです。
何かアドバイスをいただけたらと思います。

どうぞよろしくお願い致します。
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 7

checkベストアンサー

+5

本題とはそれますが、どんな物かということであれば
参考ページ ビット演算 ビットフラグ
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で無いか調べます
select * from tb where (flags & 8) > 0
・flag1とflag6の両方がonのレコードを得たければ合計値とビットANDを行って同じかを調べます
select * from tb where (flags & (1+32)) = 33
・flag1かflag6の片方がonのレコードを得たければ合計値とビットANDを行って0で無いか調べます
select * from tb where (flags & (1+32)) > 0
・flag1,flag2,flag4がonで他は全てoffのレコードを得たければ合計値と一致するかを調べます
select * from tb where flags = 11
ビット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/02 09:46

    ありがとうございます。
    非常に的確でとてもわかりやすいご説明に感謝します!
    そして短所が多く、ビットフラグはオススメではないのですね。

    >まずはそのシステム設計を見直すべきです。

    Web側でユーザーが様々な設定のチェックボックスにチェックしたり外したりしますが、その値を保存するためのカラムとしてflag1~6まで用意しました。今後このチェックボックスが増える可能性はあります。

    そこでシステム設計を見直すとありますが、実際にはカラムをこのようなチェックボックス的な使い方はしないのでしょうか?もし他に方法があるのでしたらお教え頂きたいと思います。

    キャンセル

  • 2015/08/02 10:06 編集

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

    アンケートの回答管理など、項目が事前に定まらず運用中も増減するものなら正規化してしまうのもありだと思いますが、今回のようなケースだとやはり今のままで良いのではないかと思います。

    キャンセル

  • 2015/08/02 10:14

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

    キャンセル

  • 2015/08/04 18:25

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

    キャンセル

+2

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/01 23:44

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

    参考にさせて頂きたいと思います!

    キャンセル

  • 2015/08/02 01:21

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

    キャンセル

  • 2015/08/02 09:38 編集

    ありがとうございます。
    たしかにディスク容量的な節約は考慮しなくてもいいレベルですね…。

    そもそも、このようなチェックボックス的なフラグをカラムで持つということ自体、データベース設計において正規化してないし無駄と思われそうで質問させて頂きました。

    私は仕事でデータベースを扱っているわけではないので(勉強の段階です)、他の人が私のデータベース設計を見ることはないのですが、実際に事業プロジェクトとしてプロの方々が設計する場合、このようなチェックボックス的なカラムはアリなのでしょうか?

    キャンセル

  • 2015/08/02 10:24

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

    キャンセル

  • 2015/08/02 10:36

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

    キャンセル

  • 2015/08/03 09:07

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

    キャンセル

+1

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/01 23:42 編集

    ありがとうございます。

    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/02 00:21

    「どういう意味」かというのはそうじゃなくて…

    キャンセル

  • 2015/08/02 00:27

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

    キャンセル

+1

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/01 23:50

    ありがとうございます。

    >投入可かどうかの判定に部品の番号に対応したビットがONならば投入できるという判断をしました。

    というのは、1~52の例えば30番のビットをONにし、その他の番号はONにすることはない、ということでしょうか?例えば30番と18番をONにするなど複数のビットをONにするということはしないという感じですか?

    ビットフラグを実際に使ったことがないのですが、なんとなく複数のビットの判定ってどうやるんだろう?という漠然とした疑問はあります。

    キャンセル

  • 2015/08/02 07:22 編集

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

    キャンセル

+1

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/02 09:41

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

    キャンセル

+1

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

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

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/04 18:24

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

    キャンセル

0

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/08/04 18:31

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

    キャンセル

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

  • ただいまの回答率 90.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • MySQL

    5995questions

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