mysql如何实现简单推荐逻辑_mysql项目入门示例

来源:这里教程网 时间:2026-02-28 20:44:30 作者:

用 GROUP BY + ORDER BY 实现协同过滤雏形

不需要机器学习库,MySQL 本身就能跑出“买了这个的人也买了那些”的基础推荐。核心思路是:找出和目标用户行为相似的其他用户,再取他们买过但目标用户没买过的商品。

假设表结构为

orders(user_id, product_id, created_at)
,想给用户 123 推荐:

先查出用户 123 购买的全部
product_id
再查所有购买过这些商品的其他用户(排除 123 自己) 统计这些“相似用户”购买频次最高的商品(且不在用户 123 的历史中)
SELECT product_id, COUNT(*) AS cnt
FROM orders
WHERE user_id IN (
  SELECT DISTINCT user_id
  FROM orders
  WHERE product_id IN (
    SELECT product_id FROM orders WHERE user_id = 123
  ) AND user_id != 123
)
AND product_id NOT IN (
  SELECT product_id FROM orders WHERE user_id = 123
)
GROUP BY product_id
ORDER BY cnt DESC
LIMIT 5;

避免笛卡尔积导致查询爆炸

上面 SQL 在数据量稍大(比如相似用户超 5000 个)时会变慢,因为子查询嵌套+

NOT IN
容易触发全表扫描。真实项目中必须加索引,且改写为
LEFT JOIN
避免
NOT IN
对 NULL 敏感的问题。

强制建立联合索引:
ALTER TABLE orders ADD INDEX idx_uid_pid (user_id, product_id);
NOT IN
换成
LEFT JOIN ... IS NULL
,更稳定
如果用户行为稀疏(每人只买几个),先用临时表存“种子商品”,再分步关联,比单条 SQL 更可控

冷启动时 fallback 到热门或新品

新用户没任何购买记录,上面逻辑直接返回空。不能卡住,得有兜底策略:

按销量排序:
SELECT product_id FROM orders GROUP BY product_id ORDER BY COUNT(*) DESC LIMIT 5
按上架时间倒序(假设你有
products(created_at)
表)
混合策略:热门 × 0.7 + 7 天内新品 × 0.3,用
UNION ALL
后加
LIMIT
控制总数

注意别在主查询里实时算热度权重,应预计算到缓存表或加字段(如

products.hot_score
),否则每次推荐都扫全表。

为什么不用 JOIN 直接连三张 orders 表

有人尝试写三层

JOIN
模拟用户-商品-用户关系链,结果查几秒不出结果甚至 OOM。MySQL 的 JOIN 优化器对多层自连接非常不友好,尤其当
orders
表超百万行时,中间结果集极易膨胀。

用子查询明确切分步骤,让执行计划更可控 每步加
LIMIT
(比如先取 top 100 相似用户)可大幅提速,牺牲一点精度换响应时间
真正上线前务必用
EXPLAIN FORMAT=TREE
看是否走了索引,以及 rows 估算是否合理

推荐逻辑越简单,越要盯死执行计划和实际耗时——看起来一行 SQL 很轻量,背后可能扫千万行。

相关推荐