如何生成排除上周菜品且无同首词重复的随机周菜单
解决方案
方法一:使用窗口函数(MySQL 8.0+ 及其他支持窗口函数的数据库)
这种写法逻辑清晰,利用ROW_NUMBER()窗口函数按首词分组,每组内随机选取一个菜品,再从中随机筛选7个:
SELECT id FROM ( SELECT f.id, SUBSTRING_INDEX(f.name, ' ', 1) AS first_word, ROW_NUMBER() OVER (PARTITION BY SUBSTRING_INDEX(f.name, ' ', 1) ORDER BY RAND()) AS rn FROM foods f -- 替换weeks表的查询条件为实际业务逻辑,比如按日期筛选上周记录 WHERE f.id NOT IN (SELECT id FROM weeks WHERE week = DATE_SUB(CURDATE(), INTERVAL 1 WEEK)) ) AS filtered WHERE rn = 1 ORDER BY RAND() LIMIT 7;
关键说明
SUBSTRING_INDEX(f.name, ' ', 1):按空格分割菜品名称,提取首词,若你的菜品名用其他分隔符,替换空格即可ROW_NUMBER() OVER (...):对每个首词分组内的菜品随机排序,标记每组的第一个菜品(rn=1)- 内层子查询先排除上周吃过的菜品,外层从每个首词的唯一菜品中随机选7个
方法二:兼容低版本MySQL(无窗口函数支持)
利用GROUP_CONCAT和SUBSTRING_INDEX实现每组随机选一个,适合MySQL 5.x等版本:
SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY RAND()), ',', 1) AS id FROM foods WHERE id NOT IN (SELECT id FROM weeks WHERE week = DATE_SUB(CURDATE(), INTERVAL 1 WEEK)) GROUP BY SUBSTRING_INDEX(name, ' ', 1) ORDER BY RAND() LIMIT 7;
关键说明
GROUP_CONCAT(id ORDER BY RAND()):每个首词分组内,将菜品ID随机拼接成字符串SUBSTRING_INDEX(..., ',', 1):从拼接字符串中取第一个ID,即该首词下随机选的菜品
注意事项
- 替换
name为你的菜品表中存储名称的实际字段名 - 调整
weeks表的查询条件,匹配你实际记录上周菜品的逻辑(比如按日期范围筛选而非week字段) - 若首词分割规则特殊(如连字符、下划线),修改
SUBSTRING_INDEX的分隔符参数
内容的提问来源于stack exchange,提问作者erre
相关产品推荐
相关产品推荐

