2014-01-16 23 views
0

我正在維護一個專注於銷售服裝的電子商務網站(在LAMP中)。SQL模式設計:在獲取數據時多對多的關係麻煩

數據庫最重要的表格就是服裝表。

此表有一個像「服裝名」,「服裝類」,「服裝風格」

有在數量上佔一些風格領域。

例如,

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. 以這種方式實現多對多關係(將所有值存儲在一個由逗號分隔的字段中)是一種不好的做法?如果是這樣,有什麼更好的解決方案?

我很欣賞任何建議。

非常感謝你,對不起我的可憐的英語。

+1

1.請參閱2. 2.這是不好的做法。見正常化。 – Strawberry

回答

1

您可以使用FIND_IN_SET檢查,看是否有一件衣服具有一定的風格:

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

這將產生0爲服裝任何片段,而不會風格2.

此錯誤的通常模式是將有三個表。您現有的服裝表:

clothing 
id   clothing_name 

新clothing_style表:

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; 
+0

FIND_IN_SET正是我現在所需要的。非常感謝你。你真的幫我我的兩個問題:D –

+0

btw,因爲FIND_IN_SET的存在,也許它不是真的不好實踐存儲字符串通知列中的數組? :) –

+1

@尤川豪我不會說這是很好的做法,因爲有一種方法可以幫助。如果服裝款式不太可能改變,那麼使用'FIND_IN_SET'可能沒有任何傷害。 – Jim

2

我的建議是,不要存儲字符串通知數組在任何列的表。使用多行這一點。它增加沒有行,但讓你的工作更容易使用的是complax查詢時 類似的東西

'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. 爲了讓所有可愛的衣服做這樣的查詢:

    SELECT * 從服裝 WHERE clothing_style LIKE'%2%'

  2. 你是對的:使用多於一個值的列不太好 - 我的建議:

你已經有你的'衣服'表 - 我想它有一個ID。除去 clothing_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

使用'clothing_style LIKE'%2%''也會給衣服帶上'12'風格。 – Jim

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,這是一個非常不好的做法,尤其是當你有大的表和性能是一個問題。它確實簡化了許多查詢,但......