SQL Server新手求助:不使用ORDER BY子句生成DENSE_RANK()的方法
解决SQL Server无ORDER BY的DENSE_RANK需求
嘿,作为SQL Server新手能想到用DENSE_RANK()已经很赞啦!不过你提到要去掉ORDER BY子句,得先理清一个关键点:排名函数(比如DENSE_RANK)本身依赖排序规则来确定排名顺序——你想要的排名其实是按照Report No在数据里首次出现的先后顺序生成的对吧?
核心思路
因为数据库默认返回的行顺序是不确定的(没有ORDER BY时,SQL Server不保证行的输出顺序),所以我们得先给每行分配一个能代表其出现顺序的序号,再基于这个序号来计算排名。这里可以用ROW_NUMBER()配合ORDER BY (SELECT NULL)来获取数据的默认存储顺序(注意:如果表有聚集索引,这个顺序是稳定的;如果没有,后续数据变更可能影响顺序,最好用明确的业务列替代,比如创建时间、自增ID)。
具体SQL示例
假设你的表名为Reports,存储报表编号的列是ReportNo,可以用CTE(公共表表达式)来实现:
-- 第一步:给每行分配一个代表出现顺序的序号 WITH OrderedReports AS ( SELECT ReportNo, ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RowSeq FROM Reports ), -- 第二步:基于序号计算DENSE_RANK RankedReports AS ( SELECT ReportNo, DENSE_RANK() OVER(ORDER BY RowSeq) AS Rank FROM OrderedReports ) -- 输出最终结果 SELECT ReportNo, Rank FROM RankedReports;
补充说明
ORDER BY (SELECT NULL)是SQL Server的一个小技巧,让ROW_NUMBER()按照数据的默认存储顺序生成序号,这样相同的ReportNo会因为首次出现的顺序相同而获得相同的排名,完全匹配你给出的示例效果。- 如果你的表有类似
CreateTime(创建时间)或者ID(自增主键)这类能确定顺序的列,把(SELECT NULL)替换成这个列会更可靠,比如ORDER BY CreateTime,避免默认存储顺序变化带来的排名波动。
内容的提问来源于stack exchange,提问作者Parita Navadiya
相关产品推荐
相关产品推荐

