2012-06-18 104 views
2

我試圖找出一個查詢檢索特定產品在類別列表。如何使用joins和group_concat正確檢索產品主要和次要類別?

我有了三個表稱爲類,product_to_sec_cat_assoc和產品數據庫稱爲產品。

+--------------------+ +--------------------+ +--------------------------+ 
| Products   | | categories   | | product_to_sec_cat_assoc | 
+--------------------+ +--------------------+ +--------------------------+ 
| product_id   | | category_id  | | product_id    | 
| pri_category_id | | category_name  | | category_id    | 
| name    | | url_link   | +--------------------------+ 
+--------------------+ +--------------------+ 

由於並非所有產品都具有次級類別,因此我將其主要類別直接歸入產品條目中。如果他們也在其他次要類別中,我使用名爲product_to_sec_cat_assoc的關聯表來關聯其他類別。

我在編寫查詢時遇到了麻煩,我想在其中創建一個顯示特定類別中所有產品的頁面。每款產品上市也顯示了各種繼發性兩類他們在

我當前的查詢是:

select t.*, 
GROUP_CONCAT(c.category_name order by pri_category_id, c.category_id) as category_names, 
GROUP_CONCAT(c.url_link) as category_links from products t 
left join product_to_sec_category_assoc a using (id) 
left join categories c on t.pri_category_id = c.category_id or c.category_id = a.category_id 
where t.pri_category_id = 12 
or (a.category_id = 12 and a.id = t.id) 
group by t.title 

出於某種原因,不過,如果我將產品添加到一個以上的次級類,當我查看在其中一個次要類別中的產品,它僅顯示我正在查看的主要類別和次要類別。另一方面,如果我查看主要類別列表,它將顯示主要類別及其所有次要類別。

例如,假設我在電子主類別以及平板電腦和移動次要類別中使用了iPad。如果我訪問電子產品類別列表,它會顯示電子產品,平板電腦,手機中的iPad。如果我進入移動類別,它將顯示在電子,移動。如果我進入Tablet類別,它會在Electronics,T​​ablet類別中顯示它。

我遇到的另一個問題是,該查詢也沒有正確命令GROUP_CONCAT(category_name)和GROUP_CONCAT(category_link),以便category_names及其鏈接處於匹配順序。

回答

2

考慮到您的設計(產品有兩種不同的類別關係),您的問題相當棘手。問題在於,在WHERE條款中,您基本上過濾掉了其餘產品的類別,並且只返回用戶所在的類別和/或其主類別。

相反,你必須首先選擇具有特定類別無論是在二級分類表或在其主類別字段(FROM子查詢完成)然後加入結果是到次級產品,分類表 - 這樣你得到所有類別的是在特定類別的產品(不管是不是它的主要類別):

SELECT 
    a.*, 
    GROUP_CONCAT(DISTINCT CONCAT(c.category_name, '||', c.url_link) ORDER BY c.category_name) AS categories 
FROM 
    (
     SELECT 
      aa.product_id, 
      aa.pri_category_id, 
      aa.name 
     FROM 
      products aa 
     LEFT JOIN 
      product_to_sec_category_assoc bb ON 
       aa.product_id = bb.product_id 
       AND bb.category_id = 12 
     WHERE 
      aa.pri_category_id = 12 
      OR bb.product_id IS NOT NULL 
    ) a 
LEFT JOIN 
    product_to_sec_cat_assoc b ON a.product_id = b.product_id 
LEFT JOIN 
    categories c ON 
     a.pri_category_id = c.category_id 
     OR b.category_id = c.category_id 
GROUP BY 
    a.product_id 
ORDER BY 
    a.title 

兩個12的表示當前的類日E用戶是

你必須注意

一件事是,在第二LEFT JOINOR會隨時加入兩行有至少一個二級類別中的每個產品 - 一行將始終是該產品的主要類別。因此,在加入視覺中,對於產品列出的每個輔助類別,您都會將產品的主要類別添加到其上,導致重複。這就是爲什麼你必須在GROUP_CONCAT()函數中引入DISTINCT

GROUP_CONCAT()中,我決定將category_nameurl_link字段合併在一起,用||分隔。根據您在應用程序中使用的語言,您可以根據該分隔符分割兩個語言。這比嘗試匹配兩個不同列中的訂單要好。


也許更好的設計是隻對我們的產品和類別之間的許多一對多的關係,並在您的交叉引用表指示類別是否爲原發性或不是現場。該模式看起來是這樣的:

+---------------+ +-------------------+ +----------------+ 
| products  | | product_cat_assoc | | categories  | 
+---------------+ +-------------------+ +----------------+ 
| product_id | | product_id  | | category_id | 
| name   | | category_id  | | category_name | 
+---------------+ | is_primary  | | url_link  | 
        +-------------------+ +----------------+ 

現在你只需要基於一個關係,而不是兩個檢索類別有關。 is_primary字段可能是TINYINT(1),包含01以指示它是否是主要的。在此設計中,所有產品在product_cat_assoc表中應始終至少有一個相應的行,代表主要類別。其他行將是次要類別。

然後檢索特定類別中的所有類別的產品列表,查詢是簡單:

SELECT 
    a.*, 
    GROUP_CONCAT(CONCAT(c.category_name, '||', c.url_link) ORDER BY b.is_primary DESC) AS categories 
FROM 
    (
     SELECT 
      aa.product_id, 
      aa.name 
     FROM 
      products aa 
     INNER JOIN 
      product_cat_assoc bb ON aa.product_id = bb.product_id AND bb.category_id = 12 
    ) a 
INNER JOIN 
    product_cat_assoc b ON a.product_id = b.product_id 
INNER JOIN 
    categories c ON b.category_id = c.category_id 
GROUP BY 
    a.product_id 
ORDER BY 
    a.name 
+0

這是完美的。我不知道我想要做的事情會如此複雜,如果沒有你的幫助,我永遠也不會想出來。我和is_primary模型一起工作,工作很棒。真的很感激它。 –

相關問題