1.RANK()
在MySQL中,你可以使用窗口函数(Window Functions)来实现排名功能,特别是在MySQL 8.0及更高版本中。窗口函数允许你对查询结果集的一个子集(称为窗口)执行计算,这非常适合排名、累计总和等场景,如果你想要处理分数相同的情况,并给它们分配相同的排名,你可以使用 RANK() 或 DENSE_RANK() 函数。这两个函数之间的主要区别在于处理相同排名之后的排名编号的方式:
RANK():如果有两个或更多的记录具有相同的排名,那么下一个排名将会跳过这些相同的排名数。例如,如果有两个记录都是第一名,那么下一个记录将是第三名。
DENSE_RANK():即使有多个记录具有相同的排名,它也不会跳过任何排名数。在上面的例子中,下一个记录将是第二名。
SELECT
id,
chain_up_time,
RANK() OVER ( ORDER BY chain_up_time asc ) AS 'versionNum'
FROM
yw_chain_up
2.ROW_NUMBER()
要将versionNum(由RANK()函数生成的排名)转化为带有.0后缀的自动补充形式,并且按降序排列,您可以在查询中使用CONCAT()函数来拼接字符串。但是,请注意,RANK()函数可能会为具有相同chain_up_time值的行分配相同的排名,并且会跳过随后的排名值。如果您想要连续的编号(即使对于相同的值),您应该使用ROW_NUMBER()而不是RANK()。
以下是使用ROW_NUMBER()并添加.0后缀的示例:
SELECT
id,
chain_up_time,
CONCAT(ROW_NUMBER() OVER (ORDER BY chain_up_time ASC), '.0') AS versionNum
FROM
yw_chain_up
ORDER BY
versionNum DESC;
在这个查询中:
- ROW_NUMBER()为每一行分配一个唯一的序号,按照chain_up_time的升序排列
- CONCAT()函数将序号和字符串.0拼接在一起,形成versionNum
- 最后的ORDER BY versionNum DESC确保结果按versionNum降序排列
如果您确实想要使用RANK()(即使对于相同的chain_up_time值会有相同的排名),您可以稍微修改查询来得到相同的效果:
SELECT
id,
chain_up_time,
CONCAT(RANK() OVER (ORDER BY chain_up_time ASC), '.0') AS versionNum
FROM
yw_chain_up
ORDER BY
versionNum + 0 DESC; -- 通过将versionNum转换为数字进行降序排序
请注意,在ORDER BY子句中,我们将versionNum转换为数字(通过versionNum + 0)来进行降序排序,因为versionNum现在是一个字符串。这样做可以确保排序是基于数字部分而不是基于字符串的字典顺序。
但是,如果versionNum中有任何非数字字符(除了最后的.0),这种转换可能会导致错误或不可预测的结果。因此,使用ROW_NUMBER()可能是更可靠的选择,因为它会生成纯数字的排名,可以直接用于数字排序。