2009-03-04 163 views
1

我不確定這是否可能在MySQL中。這裏是我的表: -mySQL查詢選擇兒童

分類表:

  • ID
  • PARENT_ID(指向Categories.id)

我使用上表中的所有地圖類別和子類別。

產品表:

  • ID
  • CATEGORY_ID

產品表指向它所屬的子類別編號CATEGORY_ID。

例如如果我有玩具>教育>美國廣播公司ABC是產品,玩具是類別和教育是子類別,那麼ABC將有category_id爲2.

現在的問題是,我想使用SQL查詢來顯示所有產品(在所有子類別及其子類別中,n級別)。

例如爲:

select * from categories,products where category.name = 'Toys' and .... 

上述查詢應顯示從教育其產品和所有其他子類別及其子類別。

這可能使用mySQL查詢嗎?如果不是我有什麼選擇?我想避免PHP遞歸。

更新:基本上我想通過在產品表中添加匹配列來顯示主要類別中的前10位產品。

回答

5

我在之前需要做同樣事情的項目中所做的工作,我添加了兩個新列。

  • i_depth:類別有多深
  • nvc_breadcrumb int值:在麪包屑型格式

然後類別的完整路徑我添加了一個觸發器,裏面的表分類信息做到以下幾點(全部三次更新都在同一個觸發器)...

-- Reset all branches 
UPDATE t_org_branches 
    SET nvc_breadcrumb = NULL, 
    i_depth = NULL 

-- Update the root branches first 
UPDATE t_org_branches 
    SET nvc_breadcrumb = '/', 
     i_depth = 0 
    WHERE guid_branch_parent_id IS NULL 

-- Update the child branches on a loop 
WHILE EXISTS (SELECT * FROM t_branches WHERE i_depth IS NULL) 
    UPDATE tobA 
     SET tobA.i_depth = tobB.i_depth + 1, 
      tobA.nvc_breadcrumb = tobB.nvc_breadcrumb + Ltrim(tobA.guid_branch_parent_id) + '/' 
     FROM t_org_branches AS tobA 
      INNER JOIN t_org_branches AS tobB ON (tobA.guid_branch_parent_id = tobB.guid_branch_id) 
     WHERE tobB.i_depth >= 0 
      AND tobB.nvc_breadcrumb IS NOT NULL 
      AND tobA.i_depth IS NULL 

然後只需要對你的產品表的連接的類別ID和做一個「LIKE'%/ [CATEGORYID] /%'」。請記住,這是在MS SQL中完成的,但它應該很容易轉換爲MySQL版本。

它可能只是足夠兼容剪切和粘貼(在表和列名稱更改後)。


的解釋擴展...

t_categories(因爲它現在站立)...

Cat Parent CategoryName 
1 NULL MyStore 
2 1  Electronics 
3 1  Clothing 
4 1  Books 
5 2  Televisions 
6 2  Stereos 
7 5  Plasma 
8 5  LCD 

t_categories(修改後)...

Cat Parent CategoryName Depth Breadcrumb 
1 NULL MyStore   NULL NULL  
2 1  Electronics  NULL NULL 
3 1  Clothing  NULL NULL 
4 1  Books   NULL NULL 
5 2  Televisions  NULL NULL 
6 2  Stereos   NULL NULL 
7 5  Plasma   NULL NULL 
8 5  LCD    NULL NULL 

t_categories (使用我給出的腳本後)

Cat Parent CategoryName Depth Breadcrumb 
1 NULL MyStore   0  / 
2 1  Electronics  1  /1/ 
3 1  Clothing  1  /1/ 
4 1  Books   1  /1/ 
5 2  Televisions  2  /1/2/ 
6 2  Stereos   2  /1/2/ 
7 5  LCD    3  /1/2/5/ 
8 7  Samsung   4  /1/2/5/7/ 

t_products(因爲你擁有了它,現在,沒有修改)...

ID Cat Name 
1 8 Samsung LNT5271F 
2 7 LCD TV mount, up to 36" 
3 7 LCD TV mount, up to 52" 
4 5 HDMI Cable, 6ft 

加入類別和產品(其中類別是C,產品是P)

C.Cat Parent CategoryName Depth Breadcrumb ID p.Cat Name 
1 NULL MyStore   0  /   NULL NULL NULL 
2 1  Electronics  1  /1/   NULL NULL NULL 
3 1  Clothing  1  /1/   NULL NULL NULL 
4 1  Books   1  /1/   NULL NULL NULL 
5 2  Televisions  2  /1/2/  4 5  HDMI Cable, 6ft 
6 2  Stereos   2  /1/2/  NULL NULL NULL 
7 5  LCD    3  /1/2/5/  2 7  LCD TV mount, up to 36" 
7 5  LCD    3  /1/2/5/  3 7  LCD TV mount, up to 52" 
8 7  Samsung   4  /1/2/5/7/ 1 8  Samsung LNT5271F 

現在假設產品表更加完整,因此每個類別中都有東西,並且沒有NULL,您可以執行「Breadcrumb LIKE'%/ 5 /%'」來獲取我提供的最後一個表格的最後三個項目。請注意,它包含該類別的直接項目和子項目(如Samsung電視)。如果你只想要特定的分類項目,只需做一個「c.cat = 5」。

+0

看起來不錯。我會試試這個。 – 2009-03-05 04:50:24

0

表格分類有多大?您可能需要將其緩存在應用程序級別並構建適當的查詢:...其中id在(2,3,6,7)

另外,最好是通過id獲取類別,這是它們的唯一ID ,索引和快速,而不是按名稱查找。

+0

我如何在應用層面實現這一目標?遞歸是唯一正確的方法? – 2009-03-04 05:29:34

+0

如果表格只有100行很大,那麼您可以簡單地在類別中選擇*並在應用程序級別上操作(彙編)結構。 – cherouvim 2009-03-04 06:41:51

1

將一列添加到Categories表中,該表中將包含每個組的完整逗號分隔樹。使用你的例子,子類別教育會把它當作樹'1,2',其中1 =玩具,2 =教育(包括它本身)。下一個嵌套級別的類別將繼續添加到樹中。

要獲得所有產品在一組,你使用MySQL的FIND_IN_SET功能,像這樣

SELECT p.ID 
FROM Products p INNER JOIN Categories c ON p.category_ID = c.ID 
WHERE FIND_IN_SET(your_category_id, c.tree) 

我不會使用大表這種方法,因爲我不認爲這個查詢就可以使用索引。

0

袒護我,因爲我從來沒有做過這樣的事情。

BEGIN 
    SET cat = "5"; 
    SET temp = ""; 

    WHILE STRCMP(temp, cat) != 0 DO 
    SET temp = cat; 
    SET cat = SELECT CONCAT_WS(GROUP_CONCAT(id), cat) FROM Categories GROUP BY (parent_id) HAVING FIND_IN_SET(parent_id, cat); 
    END LOOP; 
END; 

SELECT * FROM products WHERE FIND_IN_SET(category_id, cat) 

我幾乎可以保證上述不會工作,但你可以看到我正在嘗試做什麼。我得到了這一點,我只是決定不完成查詢的結束(選擇每個類別的前N),對不起。 :P

1

一種方法是維護一個包含祖先到後代關係的表。您可以查詢此特定表並獲取所有家屬的列表。

5

我認爲最簡單的方法是使用嵌套集模型。實施起來有點複雜,但功能強大。 MySQL有一個名爲Managing Hierarchical Data in MySQL的教程。其中一位大型SQL大師Joe Celko寫了同樣的東西here。如果你需要更多的信息,請看Troel's links on storing hierarchical data

在我的情況下,我會遠離使用RDBMS來存儲這種數據並使用圖形數據庫,因爲在這種情況下的數據實際上是有向圖。

1

假設MySQL,在PHP中很難避免遞歸。

你的問題本質上是如何模仿Oracle在MySQL中的語法CONNECT BY PRIOR。人們問這個questionrepeatedly但它是一個從未進入MySQL的功能,並且通過存儲過程實現可能不會工作,因爲(現在)stored functions cannot be recursive

當心迄今爲止提供的數據庫克魯日。

最好的信息,到目前爲止都是three links from nawroth