MySql为一个单元格中的另一个表存储多个引用并选择它?

时间:2012-05-16 23:40:56

标签: php mysql select

我有两张桌子

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)多个值昏迷的更好的替代方法,请告诉我。

3 个答案:

答案 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;
        ;