2017-02-19 8 views
0

を使用してSET()を避け、問題である:のMySQL - だからここに接合し、外部キー

私はテーブルのメンバーとその属性を持つ「メンバー」(名前、誕生日、メールなど)を持っている これらのメンバーかもしれませんグループに属しています(3つのグループがあるとしましょう)。これらのグループはテーブル(「グループ」)で参照されるため、必要に応じて追加/削除/変更できます。

SET()は解決策ではないようですが、外部キー/参照表と互換性がありません。 、すべてのグループの111 (7)なしのため000 (0)、第一グループの001 (1)、第二のため010 (2)、などしかし、名前があることから:

したがって、最初に、私は私がSET()ように使用TINYINT()列を、やって考えていました非常に複雑で、混乱し、外来キーとの互換性はそれほど高くありません。

2つのテーブルの両方に参加するために3番目のテーブル「Members-Groups」をmemberIDとgroupIDで実行する必要がありますが、それがどのように機能するかはわかりません。

+----------+---------+ 
| memberID | groupID | 
+----------+---------+ 
| 1  | 1  | 
| 1  | 2  | 
| 2  | 1  | 
| 2  | 3  | 
| 3  | 2  | 
+----------+---------+ 

との接合部と組み合わせ、私は私が欲しいものを取得することができます:私は理解してどのような

は、私はこのようなメンバーとグループのIDを持つテーブルを持っているということです。そうですか?そうでなければ誰かが私に何をすべきか説明することができますか?

メンバー、属性、彼が所属するグループ(SET()など)、最終的な結果(SQLリクエスト+ PHPスクリプト後)どのグループにも属していません。

+0

結合時に表ごとに列を設定できます。 – Xorifelse

答えて

0

drop table if exists mg; 

drop table if exists m; 
create table m (id int primary key, name varchar(3)); 
insert into m values 
(1,'abc'), 
(2,'def'), 
(3,'ghi'); 

drop table if exists g; 
create table g(id int primary key ,name varchar(3)); 
insert into g values 
(1,'aaa'), 
(2,'bbb'), 
(3,'ccc'); 

create table mg 
(memid int,grid int, 
index fmid(memid,grid) , 
foreign key (memid) references m(id) on delete cascade, 
foreign key (grid) references g(id) on delete cascade 
); 
insert into mg values 
(1,1),(1,2),(1,3), 
(2,1),(2,3); 

あなたは3つのテーブルを結合し、GROUP_CONCATまたは条件付きの集約を使用して結果を生成したと仮定すると。

MariaDB [sandbox]> select m.id,m.name, group_concat(g.name) groups 
    -> from m 
    -> join mg on mg.memid = m.id 
    -> join g on mg.grid = g.id 
    -> group by m.id,m.name; 
+----+------+-------------+ 
| id | name | groups  | 
+----+------+-------------+ 
| 1 | abc | aaa,bbb,ccc | 
| 2 | def | aaa,ccc  | 
+----+------+-------------+ 
2 rows in set (0.00 sec) 

MariaDB [sandbox]> 
MariaDB [sandbox]> select m.id,m.name, 
    -> max(case when g.id = 1 then g.name else '' end) as group1, 
    -> max(case when g.id = 2 then g.name else '' end) as group2, 
    -> max(case when g.id = 3 then g.name else '' end) as group3 
    -> from m 
    -> join mg on mg.memid = m.id 
    -> join g on mg.grid = g.id 
    -> group by m.id,m.name; 
+----+------+--------+--------+--------+ 
| id | name | group1 | group2 | group3 | 
+----+------+--------+--------+--------+ 
| 1 | abc | aaa | bbb | ccc | 
| 2 | def | aaa |  | ccc | 
+----+------+--------+--------+--------+ 
2 rows in set (0.00 sec) 

いずれのグループにも属していないメンバーには、結合を左結合に変更する必要があります。

ariaDB [sandbox]> select m.id,m.name, group_concat(g.name) groups 
    -> from m 
    -> left join mg on mg.memid = m.id 
    -> left join g on mg.grid = g.id 
    -> group by m.id,m.name; 
+----+------+-------------+ 
| id | name | groups  | 
+----+------+-------------+ 
| 1 | abc | aaa,bbb,ccc | 
| 2 | def | aaa,ccc  | 
| 3 | ghi | NULL  | 
+----+------+-------------+ 
3 rows in set (0.00 sec) 

MariaDB [sandbox]> 
MariaDB [sandbox]> select m.id,m.name, 
    -> max(case when g.id = 1 then g.name else '' end) as group1, 
    -> max(case when g.id = 2 then g.name else '' end) as group2, 
    -> max(case when g.id = 3 then g.name else '' end) as group3 
    -> from m 
    -> left join mg on mg.memid = m.id 
    -> left join g on mg.grid = g.id 
    -> group by m.id,m.name; 
+----+------+--------+--------+--------+ 
| id | name | group1 | group2 | group3 | 
+----+------+--------+--------+--------+ 
| 1 | abc | aaa | bbb | ccc | 
| 2 | def | aaa |  | ccc | 
| 3 | ghi |  |  |  | 
+----+------+--------+--------+--------+ 
3 rows in set (0.00 sec) 
+0

ありがとう!私はSqlで始まり​​、高度な機能(接合点など)はあまりよく知られておらず、 'GROUP_CONCAT()'これはまさに私が望むものです:) – Mncc

+0

グループが一意であれば私のプライマリキー?そして私はIDの代わりに名前を直接使用します。 – Mncc

+0

あなたはmgからidを落として、必要に応じて名前をプライマリ・キーとして使用できますが、オーバーヘッドがあります - インデックス・サイズが大きくなり、ロジックがジャンクション・テーブル・グリッド・フィールドを操作するために同じフィールドが必要になります型と値をmg.nameとすると、このテーブルも大きくなり、グループ名フィールドを変更する必要がある場合は、いくつかの問題が予想されます。 –

0

私は質問で半分混乱しているように感じますが、私はそれを刺すでしょう。

メンバテーブルがある場合は、一意のプライマリキーにmember_idを指定すると意味があります。各メンバーが属するグループを保存する場合は、各グループのメンバーテーブルに新しい列を追加するだけです。値については

が列Group1Group2に与えられる、Group3あなたは(「0」、「1」)またはENUM(「いいえ」、「はい」)、または任意のENUMとして、それらを設定し、デフォルトを作ることができます負の意味(最初の)の値を値にします。

このdb構造では、クエリ中に文字列を切り詰める必要はありません。適切なGroupカラム値を指定するSELECT文またはWHERE文を書くだけです。

これが直接答えられない場合は、質問を明確にしてください。

+0

私はまだ同じ問題を抱えています。私は外部キーを使用できません。私は 'ENUM()'を避けるためにも読む。そして、各グループのための1つのカラム(例えば 'TINYINT(1) 'を使用していても)は良い解決策ではありません。たとえそれが最も簡単な方法だとしても – Mncc

関連する問題