我有两张桌子
table: people
id name goods_owned
1 john 1,4,3
2 Mike 2,5
3 Sam 1,5,2
4 Andy 5,3,4
-
table goods:
g_id g_name g_class
1 sugar food
2 salt food
3 boat transp
4 house habitation
5 car transp
这是表格goods
的简单示例,其实际上非常长,people
中的每个人都可以分配多个goods
,例如汽车,船,糖等没有一个人可以拥有多少和它完全随机的限制。我找不到更好的方法来存储它而不是昏迷分离,例如1,5,3
我遇到问题,我需要做出选择,例如
SELECT people.*, goods.name
FROM people
LEFT JOIN goods ON goods.g_id = people.goods_owned
WHERE name = "Sam"
然而问题是goods_owned在单元格中有多个商品ID,他们需要以某种方式分解才能得到答案:
1, Sam, sugar, car, salt
如果你知道在一个单元格中存储(例如100)多个值昏迷的更好的替代方法,请告诉我。
答案 0 :(得分:2)
您的数据库未规范化。你有repeating groups within columns。如果可能的话,您应该规范化数据库。
如果您无法更改数据库设计,可以使用FIND_IN_SET
,但这将是sloooooooow:
SELECT people.id, people.name, people.goods_owned, goods.name
FROM people
LEFT JOIN goods ON FIND_IN_SET(goods.g_id, people.goods_owned)
WHERE name = 'Sam'
答案 1 :(得分:2)
一个人可以与零,一种或多种商品相关。 好的可以与零,一个或多个人有关。
这是多对多的关系。
通常,我们通过创建第三个表来处理这个问题,这是一个"关系"指向其他两个表
table: goods_owned
people_id goods_id
1 1
1 4
1 3
2 2
2 5
3 1
3 5
3 2
4 5
4 3
4 4
这两列的组合可以指定为唯一,并可以作为表的主键。每列都可以定义为父表的外键。
CREATE TABLE goods_owned
( people_id INT UNSIGNED NOT NULL
, goods_id INT UNSIGNED NOT NULL
, PRIMARY KEY (people_id, goods_id)
, KEY FK_goods_owned_people (people_id)
, KEY FK_goods_owned_goods (goods_id)
, CONSTRAINT FK_goods_owned_people FOREIGN KEY (people_id) REFERENCES people (id)
, CONSTRAINT FK_goods_owned_goods FOREIGN KEY (goods_id) REFERENCES goods (g_id)
) ;
另一种选择,如果是一套"商品"是静态且定义明确的,并且不需要在表中表示,然后您可以使用MySQL SET数据类型,并且只有一个表。但是这种方法只适用于集合是静态的(不需要更改)。
答案 2 :(得分:1)
让我真的很无聊......
CREATE TABLE `people` (
`id` int(11) NOT NULL,
`name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
;
CREATE TABLE `goods` (
`id` int(11) NOT NULL,
`name` varchar(50) DEFAULT NULL,
`class_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
;
CREATE TABLE `goods_owned` (
`people_id` INT(11) DEFAULT NULL,
`goods_id` INT(11) DEFAULT NULL
) ENGINE=MYISAM CHARSET=latin1
;
CREATE TABLE `classes` (
`id` int(11) NOT NULL,
`class_name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
;
INSERT INTO `people` (`id`, `name`) VALUES('1','John');
INSERT INTO `people` (`id`, `name`) VALUES('2','Mike');
INSERT INTO `people` (`id`, `name`) VALUES('3','Sam');
INSERT INTO `people` (`id`, `name`) VALUES('4','Andy');
INSERT INTO `classes` (`id`, `class_name`) VALUES('1','Food');
INSERT INTO `classes` (`id`, `class_name`) VALUES('2','Trans');
INSERT INTO `classes` (`id`, `class_name`) VALUES('3','Habitation');
INSERT INTO `goods` (`id`, `name`, `class_id`) VALUES('1','Sugar','1');
INSERT INTO `goods` (`id`, `name`, `class_id`) VALUES('2','Salt','1');
INSERT INTO `goods` (`id`, `name`, `class_id`) VALUES('3','Boat','2');
INSERT INTO `goods` (`id`, `name`, `class_id`) VALUES('4','House','3');
INSERT INTO `goods` (`id`, `name`, `class_id`) VALUES('5','Car','2');
INSERT INTO `goods_owned` (`people_id`, `goods_id`) VALUES('1','1');
INSERT INTO `goods_owned` (`people_id`, `goods_id`) VALUES('1','4');
INSERT INTO `goods_owned` (`people_id`, `goods_id`) VALUES('1','3');
INSERT INTO `goods_owned` (`people_id`, `goods_id`) VALUES('2','2');
INSERT INTO `goods_owned` (`people_id`, `goods_id`) VALUES('2','5');
INSERT INTO `goods_owned` (`people_id`, `goods_id`) VALUES('3','1');
INSERT INTO `goods_owned` (`people_id`, `goods_id`) VALUES('3','5');
INSERT INTO `goods_owned` (`people_id`, `goods_id`) VALUES('3','2');
INSERT INTO `goods_owned` (`people_id`, `goods_id`) VALUES('4','5');
INSERT INTO `goods_owned` (`people_id`, `goods_id`) VALUES('4','3');
INSERT INTO `goods_owned` (`people_id`, `goods_id`) VALUES('4','4');
SELECT
people.name
, goods.name
, classes.class_name
FROM people
LEFT JOIN goods_owned ON (people.id = goods_owned.people_id)
LEFT JOIN goods ON (goods_owned.goods_id = goods.id)
LEFT JOIN classes ON (goods.class_id = classes.id)
WHERE classes.id = 1 /*Include only Food Goods*/
ORDER BY people.name;
;