
本文介绍如何使用 python 对数据库查询结果中的购物车记录按 `product_id` 和 `quantity` 组合进行分组计数,从而准确汇总同一用户下重复添加的相同商品及数量。适用于电商购物车去重、合并或显示“已添加x次”等场景。
在实际电商系统中,用户可能多次将同一商品(相同 product_id)以相同数量(如 quantity=1000)加入购物车,此时数据库中会生成多条独立记录。为优化前端展示(例如显示“2次 × 商品#2(1000件)”)或后端合并逻辑,需对这些记录按 (product_id, quantity) 二元组进行聚合计数。
以下是一个轻量、高效且不依赖 SQL 聚合的纯 Python 实现方案,适用于已从数据库获取记录列表(如通过 SQLAlchemy 的 session.execute().fetchall() 或 cursor.fetchall())的场景:
from collections import defaultdict
def count_product_quantity_for_user(records, user_id):
"""
统计指定用户在购物车中,各 (product_id, quantity) 组合的出现次数
:param records: 数据库查询返回的记录列表,每项应支持字典式访问(如 record['product_id'])
:param user_id: 目标用户的唯一标识符(int 或 str)
:return: defaultdict(int),键为 (product_id, quantity) 元组,值为出现频次
"""
counts = defaultdict(int)
for record in records:
# 确保 record 是可索引对象(如字典、namedtuple 或映射类实例)
if record.get('user_id') == user_id:
key = (record['product_id'], record['quantity'])
counts[key] += 1
return counts
# 示例调用
user_id = 582042554
counts = count_product_quantity_for_user(cart_records, user_id)
# 格式化输出
for (product_id, quantity), count in counts.items():
print(f"{count} times product_id={product_id} with quantity={quantity}")✅ 注意事项:
- records 应为已加载到内存的 Python 对象列表(非懒加载迭代器),确保可多次遍历;
- 若 quantity 是 Decimal 类型(如示例中的 Decimal('1000.00')),其与 float 或 int 不相等,但 Decimal('1000.00') == Decimal('1000') 成立,因此无需额外类型转换;
- 若需兼容不同 record 类型(如 SQLAlchemy ORM 实例),可改用 getattr(record, 'user_id', None) 替代 record['user_id'],并统一提取字段;
- 如数据量极大(>10 万行),建议优先使用 SQL 层聚合(如 GROUP BY product_id, quantity),避免内存与性能瓶颈。
该方法简洁、可读性强,便于集成至 Flask/FastAPI 等 Web 框架的购物车 API 中,是服务端数据聚合的实用范式。










