SQL架构设计:获取数据时多对多关系出现问题

时间:2014-01-16 09:59:48

标签: php mysql sql database-design

我正在维护一个专注于销售服装的电子商务网站(在LAMP中)。

最重要的数据库表是服装表。

此表包含“服装名称”,“服装类型”,“服装样式”等字段

有一些样式代表数字。

例如,

  

1 =时尚2 =可爱3 =性感4 =休闲..等等

每件衣服都可以有多种样式(以逗号分隔),因此行可能如下所示:

'clothing_name' 'clothing_style'
Nice T-shirt      1,3,11,15
Old Jeans         1,2,8
Adida T-shirt     3,4,7
Nike T-shirt      3,4,7

每当我想要展示一件衣服的款式时,我会做这样的事情:

<?php
      /* 
       * $clothing['style'] is not usable
       * so transform it into array first
       */
      $style_numbers = explode(",", $clothing['style']);
      $clothing['style_numbers'] = array();
      if (!empty($clothing['style'])){
          foreach ($style_numbers as $style_number){
            $clothing['style_numbers'][] = (int) $style_number;
          }        
      }

      // and then mapping the numbers into its corresponding names
?>
这样,我得到了一个样式数组,我可以用它来显示样式名称。

一切都很好,直到我想实现“类似服装”功能

我不知道如何为所有'可爱'服装设置SQL子句(可爱的样式代码是2)

我有两个问题

  1. 在这种情况下如何实施“类似服装”功能?

  2. 以这种方式实现多对多关系(将所有值存储在一个以逗号分隔的字段中)是一种不好的做法?如果是的话,什么是更好的解决方案?

  3. 我很感激任何建议。

    非常感谢,对不起我的英语很差。

4 个答案:

答案 0 :(得分:2)

我的建议是,不要在表的任何列中存储字符串通知数组。为此使用多行。它增加了行数,但使您的工作更轻松当您使用抱怨查询时 类似的东西

'clothing_name' 'clothing_style'
 Nice T-shirt      1
 Nice T-shirt      3
 Nice T-shirt      11
 Nice T-shirt      15
 Old Jeans         1
 Old Jeans         2
 Old Jeans         8

答案 1 :(得分:1)

  1. 为了得到所有可爱的衣服,请执行以下查询:

    SELECT * 从衣服 衣服喜欢'%2%'

  2. 你是对的:使用一列超过一个值是不是很好 - 我的建议:

  3. 你已经有了'衣服'表 - 我想它有一个id。除掉 clothes_style列并将其放入一个自己的表中,在其中存储每个样式一个自己的行:

    table clothing:
    clothing_id clothing_name
    1 Nice T-shirt
    2 Old Jeans
    3 Adida T-shirt
    4 Nike T-shirt
    
    table clothing_styles
    clothing_id clothing_style
    1 1
    1 3
    1 11
    1 15
    2 1
    2 2
    2 8
    3 3
    3 4
    3 7
    4 3
    4 4
    4 7
    

答案 2 :(得分:1)

您可以使用FIND_IN_SET检查一件衣服是否具有某种风格:

SELECT FIND_IN_SET('2',clothing_style) FROM clothing;

对于没有样式2的任何衣服,这将产生0

通常的架构是拥有三个表。你现有的服装表:

clothing
id          clothing_name

新的衣服样式表:

clothing_style
id          style_name

连接两者的表格:

clothing_clothing_style
clothing_id  clothing_style_id

这样可以更轻松地添加样式,因为代码不需要知道样式和名称之间的映射,因为它存储在数据库中。

一些例子:

-- Get all funny clothing
SELECT c.* FROM clothing c
INNER JOIN clothing_clothing_style ccs ON (ccs.clothing_id = c.id)
INNER JOIN clothing_style cs ON (ccs.clothing_style_id = cs.id AND cs.style_name = 'Funny');

-- Get list of clothing and comma separated list of styles
SELECT c.*,GROUP_CONCAT(cs.name) FROM clothing c
INNER JOIN clothing_clothing_style ccs ON (ccs.clothing_id = c.id)
INNER JOIN clothing_style cs ON (ccs.clothing_style_id = cs.id)
GROUP BY c.id;

答案 3 :(得分:1)

CREATE TABLE `clothing` (
    `cloth_id` INT(11) NOT NULL AUTO_INCREMENT,
    `cloth_name` VARCHAR(50) NOT NULL DEFAULT '0',
    `cloth_styles` VARCHAR(50) NOT NULL DEFAULT '0',
    PRIMARY KEY (`cloth_id`)
);

INSERT INTO `clothing` (`cloth_name`, `cloth_styles`) VALUES ('jeans', '2,3,4');
INSERT INTO `clothing` (`cloth_name`, `cloth_styles`) VALUES ('hat', '2');
INSERT INTO `clothing` (`cloth_name`, `cloth_styles`) VALUES ('socks', '3');

SELECT * FROM clothing WHERE FIND_IN_SET(2, cloth_styles); //only jeans and hat

http://sqlfiddle.com/#!2/ad9e8/1/0

播放

关于2,这是一个非常糟糕的做法,特别是当你有大表并且性能有问题时。虽然它确实简化了很多查询....