Mysql 如何使用联接和group_concat正确检索产品的主要和次要类别?
我试图找出一个查询来检索特定产品所处的类别列表 我有一个名为products的数据库,它有三个表,分别是categories、product_to_secu_cat_assoc和productsMysql 如何使用联接和group_concat正确检索产品的主要和次要类别?,mysql,Mysql,我试图找出一个查询来检索特定产品所处的类别列表 我有一个名为products的数据库,它有三个表,分别是categories、product_to_secu_cat_assoc和products +--------------------+ +--------------------+ +--------------------------+ | Products | | categories | | 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在电子产品、平板电脑和移动设备方面的表现。如果我进入手机类,它会在电子产品,手机中显示出来。如果我进入平板电脑类别,它会显示在电子产品、平板电脑类别中
我遇到的另一个问题是,查询也没有正确地对GROUP_CONCAT(category_name)和GROUP_CONCAT(category_link)进行排序,因此category_名称及其链接的顺序是匹配的。考虑到您的设计(产品与类别有两种不同的关系),您的问题相当棘手。问题在于,在
WHERE
子句中,基本上过滤掉了产品的其余类别,只返回用户所在的类别和/或其主要类别
相反,您必须首先在次要类别表或其主要类别字段中选择具有特定类别的产品(在FROM
subselect中完成),然后将结果连接到次要类别表中-这样,您就可以只获得特定类别中产品的所有类别(无论是否为主要类别):
这两个12
代表用户所处的当前类别
您必须注意的一点是,第二个左连接中的或将始终为每个至少有一个次要类别的产品连接两行-一行将始终是该产品的主要类别。因此,在联接中,对于产品列出的每个次要类别,您将在其顶部添加产品的主要类别,从而产生重复。这就是为什么必须在GROUP_CONCAT()
函数中引入DISTINCT
在GROUP_CONCAT()
中,我决定将category_name
和url_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),包含0
或1
,以指示它是否是primary。在这种设计中,所有产品在product\u cat\u 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
这太完美了。我不知道我要做的事情会如此复杂,如果没有你的帮助,我永远也不会明白。我使用的是is_初级模型,它工作得很好。真的很感激。
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