我定义了以下表格:
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。
答案 0 :(得分:1)
以下查询有效:(虽然我没有使用该视图)
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;