MySQL每日行排名实现:重复产品同排名需求及SQL问题
解决每日重复产品排名保持一致的SQL方案
嘿,我看你在处理爬虫抓取的产品排名问题——需要每日第一条记录排第1,重复抓取的同产品和首次出现时的排名保持一致对吧?你原来用的index()函数不是标准SQL的函数,而且逻辑上没法实现需求,我给你两个适配不同数据库的可行方案:
方案一:支持窗口函数的数据库(MySQL 8.0+、PostgreSQL、SQL Server等)
这种方案用窗口函数实现,逻辑清晰且效率较高:
WITH ranked_products AS ( SELECT product_ranking_id, Productinfo, Date, -- 按日期分组,给每行按抓取顺序分配行号(假设product_ranking_id是自增的抓取ID) ROW_NUMBER() OVER (PARTITION BY Date ORDER BY product_ranking_id) AS row_num, -- 找到当前产品在当日第一次被抓取的行号 MIN(ROW_NUMBER() OVER (PARTITION BY Date ORDER BY product_ranking_id)) OVER (PARTITION BY Date, Productinfo) AS first_row_num FROM ProductRanking ) SELECT product_ranking_id, Productinfo, Date, -- 按首次出现的行号做密集排名,确保同产品排名一致 DENSE_RANK() OVER (PARTITION BY Date ORDER BY first_row_num) AS Rank FROM ranked_products ORDER BY Date, product_ranking_id;
逻辑说明:
- 先用CTE
ranked_products处理每一行:ROW_NUMBER()按日期分组,根据product_ranking_id(爬虫抓取的顺序ID)给每行分配当日的抓取序号;- 第二个窗口函数找到每个产品在当日第一次出现的序号。
- 外层用
DENSE_RANK()按首次出现的序号排序,这样同一产品的首次序号相同,排名就完全一致;不同产品按首次出现的顺序获得连续的排名,不会有跳号。
方案二:旧版MySQL(不支持窗口函数)
如果你的数据库版本比较旧,没法用窗口函数,可以用子查询实现:
SELECT a.product_ranking_id, a.Productinfo, a.Date, ( -- 统计当前产品首次出现位置之前的不同产品数量,就是它的排名 SELECT COUNT(DISTINCT b.Productinfo) FROM ProductRanking b WHERE b.Date = a.Date AND b.product_ranking_id <= ( -- 找到当前产品在当日第一次被抓取的ID SELECT MIN(c.product_ranking_id) FROM ProductRanking c WHERE c.Date = a.Date AND c.Productinfo = a.Productinfo ) ) AS Rank FROM ProductRanking a ORDER BY a.Date, a.product_ranking_id;
逻辑说明:
先通过子查询找到当前产品在当日第一次被抓取的product_ranking_id,然后统计这个ID之前(包括)的所有不同产品的数量,这个数量就是该产品的排名——重复出现的产品会复用首次出现时的排名结果。
注意点:
如果你的product_ranking_id不是按爬虫抓取顺序自增的,记得把所有ORDER BY product_ranking_id换成实际的抓取时间字段(比如crawl_time),确保排序完全符合爬虫抓取的先后顺序。
内容的提问来源于stack exchange,提问作者F T
相关产品推荐
相关产品推荐

