2017-02-26 72 views
0

我正在製作一個產品和類別的樹。樹接受任何類別中存在的產品,無論它是父節點還是葉。如何在產品和類別應用程序樹中加入1個表格(2個不同的表格)?

這裏是我的表

#category table 
+------+-----------+-------------+ 
| ID | cat_name | parent_cat | 
+------+-----------+-------------+ 
| 1 |  TV |  NULL | 
+------+-----------+-------------+ 
| 2 | LCD |  1  | 
+------+-----------+-------------+ 
| 3 | PLASMA |  1  | 
+------+-----------+-------------+ 


#product table 
+------+-----------+-----------+ 
| ID | prd_name | prd_cat | 
+------+-----------+-----------+ 
| 1 |  LG |  1  | 
+------+-----------+-----------+ 
| 2 |  HD |  2  | 
+------+-----------+-----------+ 
| 3 | FHD |  2  | 
+------+-----------+-----------+ 

我要的是做一個選擇查詢檢索包含所有類別和產品的全樹。

我可以用這個查詢

select cat1.cat_name lvl1, cat2.cat_name lvl2 
from category cat1 left join category cat2 on cat1.ID = cat2.parent_cat 
where cat1.parent_cat is null; 

這個檢索類別給了我這樣的事情

+------+------+ 
| lvl1 | lvl2 | 
+------+------+ 
| TV | LCD | 
+------+------+ 
| TV |PLASMA| 
+------+------+ 

,當我試圖加入的產品我用這個查詢樹

select cat1.cat_name,cat2.cat_name,product.prd_name 
from category cat1 left join category cat2 on cat1.ID = cat2.parent_cat 
left join product on cat1.ID = product.prd_cat 
where cat1.parent_cat is null; 

但這個sql給了我這個結果

+-----------+-----------+-----------+ 
| cat_name | cat_name | prd_name | 
+-----------+-----------+-----------+ 
| TV  | LCD |  LG | 
+-----------+-----------+-----------+ 
| TV  | PLASMA |  LG | 
+-----------+-----------+-----------+ 

我希望產品表被視爲類別(2級)表,所以如果像TV這樣的父節點有一些子類別和子產品,我就得到了它們兩個。 如何得到一個結果樹像這樣:

+-------------+------------+------------+ 
| tree_lvl_1 | tree_lvl_2 | tree_lvl_3 | 
+-------------+------------+------------+ 
|  TV  |  LG  | NULL | 
+-------------+------------+------------+ 
|  TV  |  LCD |  HD  | 
+-------------+------------+------------+ 
|  TV  |  LCD |  FHD | 
+-------------+------------+------------+ 
|  TV  | PLASMA | NULL | 
+-------------+------------+------------+ 

電視(類)> LG(產品)

電視(類)> LCD(類別)> HD(產品)

TV(類)> LCD(類別)> FHD(產品)

TV(類)> PLASMA(類別)


編輯:這個 question,你建議是關於建立只有類別的樹,我知道如何做到這一點。我的問題是我也有 「產品」表應該加入樹作爲節點就像類!我想將類別和產品表視爲一個表(節點)

+0

你的'category'表有多深?它有3級,4級......嗎? –

+1

[從MySQL中的分層數據生成基於深度的樹(無CTE)]可能的副本(http://stackoverflow.com/questions/5291054/generating-depth-based-tree-from-hierarchical-data-in-mysql- no-ctes) – mroach

+0

@ PhamX.Bach,是這個產品樹是4級。我將在帳戶樹中應用相同的樹概念,這將更深入7層。 –

回答

1

您可以先刪除有兩個表的複雜性解決這個問題。創建結合的類別記錄與產品記錄的觀點,這樣的:

create view combi as 
    select 'P' as type, 
     id, 
     prd_name as name, 
     prd_cat as parent_id 
    from product 
    union all 
    select 'C' as type, 
     id, 
     cat_name, 
     parent_cat 
    from category; 

現在你可以做基於此視圖的查詢,並確保添加在連接條件的類型要求:

select lvl1.name as lvl1, 
      lvl2.name as lvl2, 
      lvl3.name as lvl3 
from  combi as lvl1 
left join combi as lvl2 on lvl1.id = lvl2.parent_id and lvl1.type = 'C' 
left join combi as lvl3 on lvl2.id = lvl3.parent_id and lvl2.type = 'C' 
where  lvl1.parent_id is null; 

看到它運行在SQLFiddle

| lvl1 | lvl2 | lvl3 | 
|------|--------|--------| 
| TV | LCD |  HD | 
| TV | LCD | FHD | 
| TV |  LG | (null) | 
| TV | PLASMA | (null) | 
+0

你是一個天使。這是我正在嘗試做的 –

+0

我的模式(產品表和類別表)是否良好?或者你建議改變它?可能有1個表(產品和類別)具有相同的視圖字段(id,name,parent),另一個表用於其他產品字段(例如條形碼,銷售價格等)。對不起,打擾你。 –

+1

如果您確實要經常使用此視圖,那麼按照您的建議進行操作可能會很有幫助。另一方面,保持它也不壞。 – trincot

0

您在此處擁有的帳戶不是不平衡的層次結構(分層樹的各分支具有不同的長度),而是層次分明的層次結構。

層次是參差不齊的,當你有一個固定的最低水平(產品,你的情況)和不平衡的層次上面(類別,你的情況)

所以,從理論上講:

cat_l1|cat_l2|prd 
TV |NULL |LG 
TV |LCD |HD 
TV |LCD |FHD 
TV |PLASMA|NULL 

我的回答基於事實上的標準設計和填充包含這種類型的層次結構的維度表。 最低級別是主鍵級別,所以它是產品。而經典的桌面設計首先將主鍵。然後,我繼續按列中的預期基數的順序 - 降低層次結構的級別。

通過人爲地平衡所有級別,但最低級別來填充不規則層次結構中的填充孔:您將父級別向下複製,直到所有級別都填滿。

您沒有PLASMA子類別的產品。通過這種設計,您不需要爲該子類別創建任何行,也可以使用例如負ID創建「不適用」的產品條目。像這樣:

cat_l1|cat_l2|prd 
TV |TV |LG 
TV |LCD |HD 
TV |LCD |FHD 
TV |PLASMA|not applicable 

下面的腳本壓制了沒有產品的子類別。要將其更改爲返回上面的報告,您必須將最後一個子類別級別的LEFT OUTER JOIN加入到產品中,並使用IFNULL(prd_name,'not applicable') AS prd_name。 不完全是你所要求的,但遵循一些事實上的標準...... 輸入數據包含在查詢中;你所要做的就是去除WITH子句。

WITH 
    category(cat_id,cat_name,parent_cat) AS (
         SELECT 1,'TV',NULL::INT 
    UNION ALL SELECT 2,'LCD',1 
    UNION ALL SELECT 3,'PLASMA',1 
    ) 
    , 
    product(prd_id,prd_name,prd_cat) AS (
         SELECT 1,'LG',1 
    UNION ALL SELECT 2,'HD',2 
    UNION ALL SELECT 3,'FHD',2 
    ) 
    SELECT 
     prd.prd_id  AS prd_id 
    , cat_l1.cat_name AS cat_l1_name 
    , cat_l1.cat_name AS cat_l2_name 
    , prd.prd_name  AS prd_name 
    FROM category cat_l1 
    JOIN product prd 
     ON prd_cat = cat_l1.cat_id 
    WHERE cat_l1.parent_cat IS NULL 
    UNION ALL 
    SELECT 
     prd.prd_id  AS prd_id 
    , cat_l2.cat_name AS cat_l2_name 
    , cat_l1.cat_name AS cat_l1_name 
    , prd.prd_name  AS prd_name 
    FROM category cat_l1 
    JOIN category cat_l2 
     ON cat_l2.parent_cat = cat_l1.cat_id 
    JOIN product prd 
     ON prd_cat = cat_l2.cat_id 
    WHERE cat_l1.parent_cat IS NULL 
    ; 

prd_id|cat_l1_name|cat_l2_name|prd_name 
    1|TV   |TV   |LG 
    2|LCD  |TV   |HD 
    3|LCD  |TV   |FHD 

玩的開心....

馬爾科理智

+2

Mysql只支持v8.0中的CTE,它甚至不處於apha狀態,所以您的解決方案對於mysql並不是很有用。 – Shadow

+0

更改CTE-S在線選擇-s ... – marcothesane

+1

這是你的amswer,不是我的。 – Shadow

相關問題