You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

商品与类别多对多关联查询去重并聚合类别名的SQL问题

解决多对多关联查询中商品重复并聚合类别名称的问题

核心思路

通过分组聚合将同一商品的多个类别名称合并成集合或字符串,同时确保商品信息唯一返回。

具体实现方案

1. SQL层面直接处理(主流数据库示例)

MySQL环境

利用GROUP_CONCAT()聚合类别名称,配合GROUP BY按商品唯一字段分组:

SELECT 
    p.id,
    p.name,
    p.price,
    GROUP_CONCAT(c.name SEPARATOR ', ') AS category_names
FROM product p
JOIN product_category pc ON p.id = pc.product_id
JOIN category c ON pc.category_id = c.id
WHERE p.name LIKE '%目标名称%' -- 替换为你的名称筛选条件
GROUP BY p.id, p.name, p.price; -- 按商品所有非聚合字段分组
  • 说明:GROUP_CONCAT()会把同一商品的所有类别名称用指定分隔符拼接成字符串;GROUP BY必须包含所有未被聚合的商品字段,避免语法错误。如果需要返回数组格式,MySQL 8.0+可改用JSON_ARRAYAGG(c.name)。

PostgreSQL环境

改用STRING_AGG()函数实现聚合:

SELECT 
    p.id,
    p.name,
    p.price,
    STRING_AGG(c.name, ', ') AS category_names
FROM product p
JOIN product_category pc ON p.id = pc.product_id
JOIN category c ON pc.category_id = c.id
WHERE p.name LIKE '%目标名称%'
GROUP BY p.id, p.name, p.price;
  • 若需数组格式,可使用ARRAY_AGG(c.name)。

2. 后端代码层处理(无法修改SQL时)

如果因业务限制不能调整SQL,可在接口逻辑中对原始查询结果去重合并,以Java伪代码为例:

// 假设原始查询返回的列表是List<ProductRaw>,包含商品+单个类别信息
Map<Long, ProductDto> productMap = new HashMap<>();
for (ProductRaw item : originalList) {
    ProductDto dto = productMap.get(item.getProductId());
    if (dto == null) {
        dto = new ProductDto();
        dto.setId(item.getProductId());
        dto.setName(item.getProductName());
        dto.setPrice(item.getPrice());
        dto.setCategories(new ArrayList<>());
        productMap.put(item.getProductId(), dto);
    }
    dto.getCategories().add(item.getCategoryName());
}
// 最终结果转换为列表
List<ProductDto> resultList = new ArrayList<>(productMap.values());

关键注意事项

  • SQL分组时,GROUP BY的字段必须能唯一标识商品(通常是主键+其他必填字段),否则会导致商品信息丢失或错误合并。
  • 聚合函数的分隔符可根据需求调整,比如用;或换行符,适配前端展示需求。

内容的提问来源于stack exchange,提问作者Frentzen Chan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 11:15:56