MySql - 避免使用联结键和外键进行 SET()
MySql - Avoid SET() using junction and foreign keys
问题来了:
我有一个 table "Members",其中包含成员及其属性(姓名、生日、邮件等)
这些成员可能属于组(假设有 3 个组),从 none 到所有组。这些组在 table ("Groups") 中被引用,所以我可以 add/delete/modify 随心所欲。
SET()
似乎不是一个解决方案,它与外键不兼容/引用 table.
所以起初,我想做一个 TINYINT()
专栏,我像 SET()
一样使用它:111 (7)
用于所有组,000 (0)
用于 none,001 (1)
代表第一组,010 (2)
代表第二组,等等。但由于名称非常复杂,很容易混淆,而且与外键的兼容性也不高。
我读到我应该使用 memberID 和 groupID 进行第三次 table "Members-Groups" 以加入我的两个 table,但我不清楚它是如何工作的.
据我所知,我将有一个 table,其中包含成员和群组的 ID,如下所示:
+----------+---------+
| memberID | groupID |
+----------+---------+
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 3 |
| 3 | 2 |
+----------+---------+
结合联结我可以检索我想要的东西。这样对吗 ?否则有人可以解释我应该怎么做吗?
我明确表示我希望最终结果(在 sql 请求 + php 脚本之后)一个成员,他的属性和他所属的组在一行中(如SET()
), 即使是不属于任何组的成员。
我觉得 half-confused 这个问题,但我会试一试。
如果您有成员 table,那么将 member_id 作为唯一主键是有意义的。如果要存储每个成员所在的组,只需为每个组向成员 table 添加一个新列。
至于要给列 Group1
、Group2
、Group3
的值,您可以将它们设置为 ENUM('0','1') 或 ENUM('No','Yes') 或其他什么,并将默认值设置为 negative-meaning(第一个)值。
有了这个数据库结构,您就不必在查询过程中费心切碎字符串了——您只需编写 SELECT 或 WHERE 语句来指定适当的组列值。
如果这不能直接回答,请澄清您的问题。
假设
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)
问题来了:
我有一个 table "Members",其中包含成员及其属性(姓名、生日、邮件等) 这些成员可能属于组(假设有 3 个组),从 none 到所有组。这些组在 table ("Groups") 中被引用,所以我可以 add/delete/modify 随心所欲。
SET()
似乎不是一个解决方案,它与外键不兼容/引用 table.
所以起初,我想做一个 TINYINT()
专栏,我像 SET()
一样使用它:111 (7)
用于所有组,000 (0)
用于 none,001 (1)
代表第一组,010 (2)
代表第二组,等等。但由于名称非常复杂,很容易混淆,而且与外键的兼容性也不高。
我读到我应该使用 memberID 和 groupID 进行第三次 table "Members-Groups" 以加入我的两个 table,但我不清楚它是如何工作的.
据我所知,我将有一个 table,其中包含成员和群组的 ID,如下所示:
+----------+---------+
| memberID | groupID |
+----------+---------+
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 3 |
| 3 | 2 |
+----------+---------+
结合联结我可以检索我想要的东西。这样对吗 ?否则有人可以解释我应该怎么做吗?
我明确表示我希望最终结果(在 sql 请求 + php 脚本之后)一个成员,他的属性和他所属的组在一行中(如SET()
), 即使是不属于任何组的成员。
我觉得 half-confused 这个问题,但我会试一试。
如果您有成员 table,那么将 member_id 作为唯一主键是有意义的。如果要存储每个成员所在的组,只需为每个组向成员 table 添加一个新列。
至于要给列 Group1
、Group2
、Group3
的值,您可以将它们设置为 ENUM('0','1') 或 ENUM('No','Yes') 或其他什么,并将默认值设置为 negative-meaning(第一个)值。
有了这个数据库结构,您就不必在查询过程中费心切碎字符串了——您只需编写 SELECT 或 WHERE 语句来指定适当的组列值。
如果这不能直接回答,请澄清您的问题。
假设
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)