2017-02-19 86 views
0

所以這裏的問題是:MySQL的 - 避免SET()使用結鍵和外鍵

我有一個表「成員」與成員和他們的屬性(姓名,生日,郵件等) 這些成員可能屬於羣體(假設有3個羣體),從無到有。這些組在表格中引用(「組」),以便我可以根據需要添加/刪除/修改它們。

SET()似乎並不是一個解決方案,它與外鍵/引用表不兼容。

所以剛開始,我就在想做得TINYINT()列,這是我使用像SET()的:111 (7)所有羣體,000 (0)是無,001 (1)爲第1組,010 (2)爲第二等,但由於名稱相當複雜,令人困惑,並且與外鍵不兼容。

我讀到我應該用memberID和groupID做一個第三個表「Members-Groups」來加入我的兩個表,但我不清楚它是如何工作的。

我明白那是什麼,我將有這樣的成員和集體的ID表:

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

,並結合結我可以找回我想要的。這樣對嗎 ?否則有人可以解釋我應該怎麼做?

我確切地說我希望最終結果(在sql請求+ php腳本之後)成員,他的屬性和他所屬的組在單行中(與SET()一樣),甚至包含成員,不屬於任何組。

+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作爲唯一的主鍵。如果要存儲每個成員所在的組,只需在每個組的成員表中添加一個新列即可。

至於值給予Group2Group1Group3你可以將它們設置爲ENUM(「0」,「1」)或ENUM(「否」,「是」),或者任何做出默認評價負面意義(第一)價值。

有了這個db結構,在查詢過程中就不用費心去琢磨一個字符串 - 只需編寫SELECT或WHERE語句來指定適當的Group列值。

如果這不直接回答,請澄清您的問題。

+0

我仍然有同樣的問題,我不能使用外鍵。我也閱讀避免'ENUM()'。每組有一列(例如,甚至使用「TINYINT(1)」)並不是我認爲的好解決方案。即使這是最簡單的方式 – Mncc