簡體   English   中英

需要MySQL JOIN才能返回產品所屬的每個類別,即使只搜索一個類別

[英]Need a MySQL JOIN to return all categories a product is in, per product, even if only one category is searched for

我定義了以下表格:

CREATE TABLE products (
    product_id INTEGER(11) NOT NULL AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    section VARCHAR(255) DEFAULT NULL,
    PRIMARY KEY (product_id)
) ENGINE=MyISAM;

CREATE TABLE categories (
    category_id INTEGER(11) NOT NULL AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    PRIMARY KEY (category_id)
) ENGINE=MyISAM;

CREATE TABLE product_categories (
    product_id INTEGER(11) NOT NULL,
    category_id INTEGER(11) NOT NULL,
    PRIMARY KEY (product_id, category_id)
) ENGINE=MyISAM;

實際上還有更多,這是優化更大,更復雜的查詢的一部分。 部分原因是將一些緩慢的子查詢移動到視圖中,這對視圖有很大幫助。

當我添加categories / product_categories表並且允許用戶按products.section或categories.category_id搜索時,查詢變得非常慢。 UI將這些作為搜索參數傳遞給我,並且我試圖獲得每個產品的行,其中包含其ID,名稱,部分以及與其關聯的以逗號分隔的類別名稱列表。 通過以下視圖和查詢,我能夠更快地完成:

CREATE OR REPLACE
ALGORITHM = MERGE
VIEW view_products_with_categories
AS
SELECT 
    p.product_id,
    p.name,
    p.section,
    pc.name AS category
products p
LEFT JOIN product_categories pc on p.product_id = pc.product_id
LEFT JOIN categories c ON pc.category_id = c.category_id;

SELECT
    product_id,
    name,
    section,
    GROUP_CONCAT(DISTINCT category ORDER BY category) AS categories
FROM view_products_with_categories
GROUP BY product_id;

假設我們有以下行:

product_id  name               section          category_id category
332913      Model Train Engine child-and-baby   1160        child-and-baby>baby-and-pre-schooltoys>playsets
332913      Model Train Engine child-and-baby   1308        toys>baby-and-preschool>playsets
332913      Model Train Engine child-and-baby   1312        toys>carstrains-and-planes>cars-and-vehicles

上面的簡單查詢給出了以下內容:

product_id  name                section         categories
332913      Model Train Engine  child-and-baby  child-and-baby>baby-and-pre-schooltoys>playsets,toys>baby-and-preschool>playsets,toys>carstrains-and-planes>cars-and-vehicles

那沒關系,正如預期的那樣。 但是,我希望用戶能夠通過category_id進行搜索。 目前,我們的UI在類別名稱上做了一些自動完成的魔術,並為動態生成的SQL添加了一個過濾器,其中包含了category_id。 如果我在GROUP_CONCAT查詢中離開了category_id,它將是1160.假設他們想要搜索第二個(1308),所以我們修改查詢,如下所示:

SELECT
    product_id,
    name,
    section,
    GROUP_CONCAT(DISTINCT category ORDER BY category) AS categories
FROM view_products_with_categories
WHERE category_id = 1308
GROUP BY product_id;

現在我們得到以下內容:

product_id  name                section         categories
332913      Model Train Engine  child-and-baby  toys>baby-and-preschool>playsets

再一次,正是你所期待的。 但是,客戶希望查看與產品相關的所有類別,這些類別包含他們正在搜索的一個或多個類別。 那么,讓我們制作一些簡化的樣本數據來向您展示我正在尋找的東西:

product_id  name       section     category_id  category
1           product_1  section_1   1            category_1
1           product_1  section_1   2            category_2 
1           product_1  section_1   3            category_3
2           product_2  section_2   3            category_3
2           product_2  section_2   4            category_4 
2           product_2  section_2   5            category_5

如果用戶搜索category_id = 3,我希望他們獲得以下內容:

product_id  name      section   categories
1           product_1 section_1 category_1, category_2, category_3 
2           product_2 section_2 category_3, category_4, category_5 

但我目前只得到:

product_id  name      section   categories
1           product_1 section_1 category_3 
2           product_2 section_2 category_3

在沒有子查詢的情況下,我無法找到一種方法,其緩慢是我首先轉向視圖的原因。 我希望有一些令人眼花繚亂的明顯我錯過了,可能是因為睡眠不足,所以任何幫助都會受到贊賞。

更新 :我還應該提到產品可能不屬於任何類別,因此我的代碼中的LEFT JOIN。

以下查詢有效:(雖然我沒有使用該視圖)

select pc1.product_id, products.name, products.section,  
  group_concat(categories.name)
from products
inner join product_categories pc1 
on (pc1.product_id =    products.product_id and pc1.category_id =  3)
inner join product_categories pc2 
on (pc2.product_id = products.product_id)
inner join categories  
on (categories.category_id = pc2.category_id)
group by pc1.product_id, products.name, products.section

如果要使用該視圖,以下內容將起作用:

SELECT  vpc.product_id,vpc.name,vpc.section,
GROUP_CONCAT(DISTINCT category ORDER BY category) AS categories
FROM view_products_with_categories vpc
inner join product_categories pc 
on (pc.product_id = vpc.product_id and pc.category_id=3) 
GROUP BY vpc.product_id, vpc.name, vpc.section;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM