
本文详解如何在 OpenCart 3 后台「总销售额报告」中,将原始按商品聚合的统计升级为按子分类(subcategory)维度聚合销量,并支持排序展示,核心在于改造 SQL 查询逻辑,利用 GROUP BY category_id 关联 oc_product_to_category 表实现分类级聚合。
本文详解如何在 opencart 3 后台「总销售额报告」中,将原始按商品聚合的统计升级为按子分类(subcategory)维度聚合销量,并支持排序展示,核心在于改造 sql 查询逻辑,利用 `group by category_id` 关联 `oc_product_to_category` 表实现分类级聚合。
在 OpenCart 3 默认的「总销售额报告」(路径:Admin → Reports → Sales → Total Sales)中,数据仅以商品(product)为单位统计销售总量(SUM(op.quantity)),未体现分类结构,更无法直观反映各子分类的销售表现。若需按子分类维度呈现销量排名(例如:显示“手机配件”子类共售出 1,247 件,“智能穿戴”子类售出 983 件),需对报表底层查询进行结构性改造。
关键改造点在于从商品粒度上移至分类粒度,并确保覆盖多级分类关系。OpenCart 使用 oc_product_to_category 表建立商品与分类的多对多映射,其中每个记录包含 product_id 和 category_id —— 这正是我们聚合的桥梁。
以下是推荐的 SQL 查询逻辑(适用于修改 /admin/model/report/order.php 中对应方法,如 getOrderTotals() 或新建 getCategorySales()):
SELECT
c.category_id,
cd.name AS category_name,
SUM(op.quantity) AS total_quantity,
SUM(op.quantity * op.price) AS total_amount
FROM `" . DB_PREFIX . "order_product` op
LEFT JOIN `" . DB_PREFIX . "order` o ON (op.order_id = o.order_id)
LEFT JOIN `" . DB_PREFIX . "product` p ON (op.product_id = p.product_id)
LEFT JOIN `" . DB_PREFIX . "product_to_category` p2c ON (p.product_id = p2c.product_id)
LEFT JOIN `" . DB_PREFIX . "category` c ON (p2c.category_id = c.category_id)
LEFT JOIN `" . DB_PREFIX . "category_description` cd ON (c.category_id = cd.category_id AND cd.language_id = '" . (int)$this->config->get('config_language_id') . "')
WHERE o.order_status_id > 0
AND o.date_added >= '" . $this->db->escape($data['filter_date_start']) . "'
AND o.date_added db->escape($data['filter_date_end']) . "'
GROUP BY c.category_id, cd.name
ORDER BY total_quantity DESC;
✅ 注意事项与最佳实践:
-
避免重复计数:若某商品属于多个分类(如同时在“手机”和“5G设备”下),上述查询会为每个关联分类分别累加该商品销量。如需“归属唯一主分类”,应在
product_to_category表中约定main_category = 1字段,或在前台逻辑中限制仅取最小category_id; -
性能优化:对
oc_order.date_added、oc_order_product.product_id及oc_product_to_category.product_id建立联合索引可显著提升查询速度; -
语言与多店兼容:示例中已通过
cd.language_id确保分类名称正确本地化;若启用多店(multi-store),需额外JOIN oc_category_to_store并添加store_id过滤; -
安全加固:务必使用
$this->db->escape()处理所有用户输入参数,防止 SQL 注入; -
扩展建议:可进一步关联
oc_category_path实现父子分类层级展示(如 “电子 > 手机 > iPhone”),提升报表可读性。
完成数据库查询改造后,还需同步更新对应的控制器(/admin/controller/report/order.php)和视图模板(/admin/view/template/report/order_total_list.twig),将新字段(category_name, total_quantity)渲染到表格中。最终效果即为:一张按子分类聚合、销量降序排列、支持时间筛选的高可用业务看板——真正让数据驱动分类运营决策。











