V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
simonlu9
V2EX  ›  程序员

mysql 怎么保证每次查出来的排名是一致的

  •  
  •   simonlu9 · 2022-09-06 16:39:32 +08:00 · 2580 次点击
    这是一个创建于 803 天前的主题,其中的信息可能已经有所发展或是发生改变。

    项目有个需求要获取用户销售额的排名,于是在 mysql 实现,但是当销售额都等于 0 的时候,排序是很不稳定的,每次获取都不一样,有什么好的解决方法呢

    SELECT
    	pos AS sort,
    	amount,
    	user_id AS userId
    FROM
    	(
    		SELECT
    			rank.*,@rank :=@rank + 1 AS pos
    		FROM
    			(
    				SELECT
    					user_id,
    					sale_amount amount
    				FROM
    					store
    				UNION
    					SELECT
    						user_id,
    						amount
    					FROM
    						store_rank
    					ORDER BY
    						amount DESC
    			) rank,
    			(SELECT @rank := 0) B
    	) c
    WHERE
    	user_id = 1015228275321995264 ;
    
    19 条回复    2022-09-07 17:45:23 +08:00
    ranleng
        1
    ranleng  
       2022-09-06 16:40:38 +08:00   ❤️ 2
    再以名字或者 user_id 排...
    chendy
        2
    chendy  
       2022-09-06 16:42:19 +08:00   ❤️ 4
    加一个创建时间之类的排序做默认顺序
    HHHHHQ
        3
    HHHHHQ  
       2022-09-06 16:51:49 +08:00
    楼上两位正解。
    wxf666
        4
    wxf666  
       2022-09-06 16:59:45 +08:00
    销售额都等于 0 时,排名不应该是一样的嘛。。

    不考虑使用连 SQLite 都支持的窗口函数 rank() OVER(...) 嘛?
    simonlu9
        5
    simonlu9  
    OP
       2022-09-06 17:18:02 +08:00
    @wxf666 当系统有多个都为 0 的数据就每次都不一样啦
    wxf666
        6
    wxf666  
       2022-09-06 17:25:03 +08:00
    @simonlu9 啥意思。。

    1. 你希望销售额相同的用户,他们的排名相同吗?

    2. 你的 SQL 最里层的『 SELECT ... UNION SELECT ... ORDER BY ...』,每次获取,结果都一样吗?
    simonlu9
        7
    simonlu9  
    OP
       2022-09-06 17:35:36 +08:00
    @wxf666 相同金额不获取的排名是不一样的,所以导致每次用户获取自己的排名不一样,所以单个字段排序是解决不了这个问题,第二个就是每次返回的结果都不一样
    wxf666
        8
    wxf666  
       2022-09-06 17:41:34 +08:00
    @simonlu9 还是没看懂。。举些例子吧,你希望是这样排名吗?

    用户 ID  销售额 排名
    ———————————
     1  100  1
     2  100  1
     3    0  3
     4    0  3
     5    0  3
    frank1256
        9
    frank1256  
       2022-09-06 17:47:32 +08:00
    order by amount desc, id desc
    eason1874
        10
    eason1874  
       2022-09-06 17:48:30 +08:00
    排序条件写两个就行了,比如其他人说的,加上 id 排序
    wineast
        11
    wineast  
       2022-09-06 17:55:22 +08:00
    加一个第二排序即可,比如 id ,创建时间 etc
    simonlu9
        12
    simonlu9  
    OP
       2022-09-06 18:01:44 +08:00
    @wxf666 谢谢你的热心回复了,我希望相同金额的用户排名是不一样的吗,
    就是比如有系统有 100 个人销售额是 0 的,那我的排名是多少呢,现在要保证每个用户的排名都是不一样的,
    上面的语句就每次返回的排名都不一样,很不稳定,所以相同销售额的排名不稳定,要额外加多一个字段,这种问题在延伸就会导致分页会出现重复的数据
    Chad0000
        13
    Chad0000  
       2022-09-06 18:02:24 +08:00
    加个排名字段定期更新?我之前就是这么干的,每小时更新排名。
    zhuweiyou
        14
    zhuweiyou  
       2022-09-06 18:09:22 +08:00
    相同的销售额, 排名应该相同才对, 参考 8 楼的图表.

    mysql 8 有排名函数.
    xiangyuecn
        15
    xiangyuecn  
       2022-09-06 18:13:03 +08:00
    相同值的本身就是乱序,谁排前面看心情。

    常规的是根据人名排序,这就是命,看投胎。
    wxf666
        16
    wxf666  
       2022-09-06 18:21:05 +08:00
    @simonlu9 感觉和前几楼说的那样,在 ORDER BY 里加个 user_id 之类的字段就好
    Xusually
        17
    Xusually  
       2022-09-06 19:20:16 +08:00 via iPhone
    简单的办法就是再加入一个不重复的排序,比如主键,user id 之类的
    dobelee
        18
    dobelee  
       2022-09-06 20:17:52 +08:00
    这是产品需求不明确,一般这种全量排行榜会是多维的,会加上注册时间、活跃时间、ID 等二重排序来避免等分乱序。
    fiveStarLaoliang
        19
    fiveStarLaoliang  
       2022-09-07 17:45:23 +08:00
    不要让它自己排序,手动加入排序规则,否则开发一时爽,维护火葬场
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5841 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 416ms · UTC 01:49 · PVG 09:49 · LAX 17:49 · JFK 20:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.