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

如何修改MySQL查询实现按baseModel字段分组且每个值仅返回1条数据

SQL查询修改方案

要实现每个baseModel仅返回一条数据,你需要调整分组逻辑,同时明确同baseModel下多条产品的筛选规则,这里我们沿用你原查询的排序规则(sort_order升序、产品名称升序),取每个分组下排序最靠前的1条数据即可。

MySQL 8.0及以上版本方案(推荐)

使用ROW_NUMBER()窗口函数实现分组排序筛选,修改后SQL如下:

SELECT * FROM (
    SELECT
        p.baseModel, 
        p.product_id,
        (
            SELECT AVG(rating) total
            FROM `oc_review` r1
            WHERE
                r1.product_id = p.product_id
                AND r1.status = '1'
            GROUP BY r1.product_id
        ) rating,
        (
            SELECT price
            FROM `oc_product_discount` pd2
            WHERE
                pd2.product_id = p.product_id
                AND pd2.customer_group_id = '1'
                AND pd2.quantity = '1'
                AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW())
                AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))
            ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1
        ) discount,
        (
            SELECT price
            FROM `oc_product_special` ps
            WHERE
                ps.product_id = p.product_id
                AND ps.customer_group_id = '1'
                AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW())
                AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW()))
            ORDER BY ps.priority ASC, ps.price ASC LIMIT 1
        ) special,
        p.viewed,
        p.sort_order,
        pd.name,
        -- 给同baseModel的产品按原规则排序编号
        ROW_NUMBER() OVER (PARTITION BY p.baseModel ORDER BY p.sort_order ASC, LCASE(pd.name) ASC) AS rn
    FROM `oc_product` p 
    LEFT JOIN `oc_product_to_category` p2c ON (p2c.product_id = p.product_id) 
    LEFT JOIN `oc_category_path` cp ON (cp.category_id = p2c.category_id)
    LEFT JOIN `oc_product_description` pd ON (p.product_id = pd.product_id)
    LEFT JOIN `oc_product_to_store` p2s ON (p.product_id = p2s.product_id)
    WHERE
        p.status = '1'
        AND p.date_available <= NOW()
        AND p2s.store_id = '0'
        AND pd.language_id = '2'
        AND cp.path_id = '291'
) t 
WHERE rn = 1 -- 每个baseModel只取排序第一的条目
LIMIT 0, 36

MySQL 5.x 版本兼容方案

如果使用的是不支持窗口函数的老版本MySQL,可以用分组关联的方式实现:

SELECT
    p.baseModel, 
    p.product_id,
    (
        SELECT AVG(rating) total
        FROM `oc_review` r1
        WHERE
            r1.product_id = p.product_id
            AND r1.status = '1'
        GROUP BY r1.product_id
    ) rating,
    (
        SELECT price
        FROM `oc_product_discount` pd2
        WHERE
            pd2.product_id = p.product_id
            AND pd2.customer_group_id = '1'
            AND pd2.quantity = '1'
            AND ((pd2.date_start = '0000-00-00' OR pd2.date_start < NOW())
            AND (pd2.date_end = '0000-00-00' OR pd2.date_end > NOW()))
        ORDER BY pd2.priority ASC, pd2.price ASC LIMIT 1
    ) discount,
    (
        SELECT price
        FROM `oc_product_special` ps
        WHERE
            ps.product_id = p.product_id
            AND ps.customer_group_id = '1'
            AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW())
            AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW()))
        ORDER BY ps.priority ASC, ps.price ASC LIMIT 1
    ) special,
    p.viewed
FROM `oc_product` p 
LEFT JOIN `oc_product_to_category` p2c ON (p2c.product_id = p.product_id) 
LEFT JOIN `oc_category_path` cp ON (cp.category_id = p2c.category_id)
LEFT JOIN `oc_product_description` pd ON (p.product_id = pd.product_id)
LEFT JOIN `oc_product_to_store` p2s ON (p.product_id = p2s.product_id)
INNER JOIN (
    -- 先查询每个baseModel下排序最靠前的product_id
    SELECT 
        p1.baseModel,
        SUBSTRING_INDEX(GROUP_CONCAT(p1.product_id ORDER BY p1.sort_order ASC, LCASE(pd1.name) ASC), ',', 1) AS target_product_id
    FROM `oc_product` p1
    LEFT JOIN `oc_product_description` pd1 ON (p1.product_id = pd1.product_id)
    WHERE
        p1.status = '1'
        AND p1.date_available <= NOW()
        AND pd1.language_id = '2'
    GROUP BY p1.baseModel
) t ON p.baseModel = t.baseModel AND p.product_id = t.target_product_id
WHERE
    p.status = '1'
    AND p.date_available <= NOW()
    AND p2s.store_id = '0'
    AND pd.language_id = '2'
    AND cp.path_id = '291'
ORDER BY p.sort_order ASC, LCASE(pd.name) ASC 
LIMIT 0, 36

注意事项

如果需要调整同baseModel下的产品筛选规则,比如取浏览量最高的产品,只需要修改窗口函数或者GROUP_CONCAT对应的ORDER BY条件即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 12:36:04