SQL Server:如何根据Name列显示行的对应排名
按文件名变体生成对应排名的解决方案
你现在遇到的问题是,原本用ROW_NUMBER() OVER (PARTITION BY ff.Name ORDER BY ff.Name)生成的RowNumber,会把每个不同的文件名当成独立分区,所以每个结果的RowNumber都是1,没法区分同一系列文件的排名顺序。而你想要的是根据文件名的后缀(比如带(1)、(2)或者无后缀)分配对应的排名,同类型的文件名共享同一个RowNumber。
思路分析
首先得把同属一个基础文件的变体归为一组,比如Invoice-02116 (1).pdf、Invoice-02116 (2).pdf和Invoice-02116.pdf都属于Invoice-02116这个基础文件。然后在这个分组内,按照后缀的优先级排序:带(1)的排第1,带(2)的排第2,无后缀的排第3,最后用能保留相同排名的函数生成RowNumber。
具体实现
我们可以用CTE先提取每个文件名的基础名,再用DENSE_RANK()来生成排名(它会给相同排序优先级的行分配相同的排名,而不是递增):
WITH BaseFileNames AS ( SELECT -- 提取基础文件名:去掉(数字)后缀和.pdf扩展名 CASE WHEN CHARINDEX('(', ff.Name) > 0 THEN LEFT(ff.Name, CHARINDEX('(', ff.Name) - 2) ELSE LEFT(ff.Name, LEN(ff.Name) - 4) END AS BaseName, ff.Name FROM YourTable ff -- 替换成你的实际表名 ) SELECT DENSE_RANK() OVER ( PARTITION BY bfn.BaseName ORDER BY -- 定义文件名的排序优先级 CASE WHEN bfn.Name LIKE '%(1).pdf' THEN 1 WHEN bfn.Name LIKE '%(2).pdf' THEN 2 ELSE 3 END ) AS RowNumber, bfn.Name FROM BaseFileNames bfn ORDER BY RowNumber, bfn.Name;
结果验证
运行这个查询后,就能得到你想要的输出:
RowNumber Name =================================== 1 Invoice-02116 (1).pdf 2 Invoice-02116 (2).pdf 3 Invoice-02116.pdf 3 Invoice-02116.pdf 3 Invoice-02116.pdf 3 Invoice-02116.pdf 3 Invoice-02116.pdf
注意事项
如果你的文件名后缀有更多变体(比如(3)、(4)),可以在CASE语句里继续添加对应的条件;如果是其他数据库(比如MySQL、PostgreSQL),字符串处理函数会略有不同,但核心思路是一致的——先分组,再按自定义规则排序,最后用DENSE_RANK生成排名。
内容的提问来源于stack exchange,提问作者DanS
相关产品推荐
相关产品推荐

