您的位置:首页 > 其它

\t\t排序参数使用变量问题 ROW_NUMBER RANK DENSE_RANK NTILE

2013-06-09 15:36 309 查看
SQL拼串功能强大,但是写起来没有提示不说,的确比较不太优雅,关键是拼串SQL将不得不接受性能上的巨大考验和脚本注入的潜在威胁。所以,“探究”安全高效的SQL实现应该是每个程序员应尽的义务^_^



create table # (data int,price int)
insert # select 1,2
insert # select 2,1
在SQL SERVER 2000中,通常是通过拼变量,然后使用EXEC执行的方法,或者采用临时表的方法处理。在ORDER BY子句中,不允许使用变量!到了2005后,SQL SERVER 提供了ROW_NUMBER() 函数方法,这给我们进行分页等需求提供了强大的支持。
DECLARE @a NVARCHAR(50)
SET @a=' data DESC '
SELECT * FROM [表名]
WHERE [条件]
ORDER BY @a
SELECT * FROM [表名]
WHERE [条件]
ORDER BY CASE @a WHEN ' data DESC ' THEN data DESC END
以上两法是错误的,对于绝大多数人来说,剩下来的,就是拼串了。

DECLARE @OrderBy NVARCHAR(100)
SET @Sort =LOWER(LTRIM(RTRIM(@Sort )));
WITH _tempT AS(
SELECT * FROM [tab1],
CASE @sort
WHEN 'date desc' THEN ROW_NUMBER() OVER(ORDER BY data desc)
WHEN 'date asc' THEN ROW_NUMBER() OVER(ORDER BY data asc)
WHEN 'price desc' THEN ROW_NUMBER() OVER(ORDER BY price desc)
WHEN 'price asc' THEN ROW_NUMBER() OVER(ORDER BY price asc)
ELSE ROW_NUMBER() OVER(ORDER BY [data])
END AS RowNumber
WHERE [各种条件]
) SELECT * FROM _tempT
WHERE RowNumber between 1 and 100ORDER BY RowNumber ROW_NUMBER、RANK、DENSE_RANK 和 NTILE,这些新函数使您可以有效地分析数据以及向查询的结果行提供排序值。您可能发现这些新函数有用的典型方案包括:将连续整数分配给结果行,以便进行表示、分页、计分和绘制直方图。ROW_NUMBER
ROW_NUMBER 函数使您可以向查询的结果行提供连续的整数值。ROW_NUMBER 总是按照请求的排序为不同的行生成不同的行号。请注意,如果在 OVER() 选项中指定的 ORDER BY 列表不唯一,则结果是不确定的。这意味着该查询具有一个以上正确的结果;在该查询的不同调用中,可能获得不同的结果。
新的排序函数的重要好处之一是它们的效率。SQL Server 的优化程序只需要扫描数据一次,以便计算值。它完成该工作的方法是:使用在排序列上放置的索引的有序扫描,或者,如果未创建适当的索引,则扫描数据一次并对其进行排序。另一个好处是语法的简单性。
可以在行组内部独立地计算排序值,而不是为作为一个组的所有表行计算排序值。为此,请使用 PARTITION BY 子句,并且指定一个表达式列表,以标识应该为其独立计算排序值的行组。
RANK, DENSE_RANK
RANK 和 DENSE_RANK 函数非常类似于 ROW_NUMBER 函数,因为它们也按照指定的排序提供排序值,而且可以根据需要在行组(分段)内部提供。但是,与 ROW_NUMBER 不同的是,RANK 和 DENSE_RANK 向在排序列中具有相同值的行分配相同的排序。当 ORDER BY 列表不唯一,并且您不希望为在 ORDER BY 列表中具有相同值的行分配不同的排序时,RANK 和 DENSE_RANK 很有用。RANK 和 DENSE_RANK 的用途以及两者之间的差异可以用示例进行最好的解释。
当 ORDER BY 列表不唯一时,ROW_NUMBER 是不确定的,而 RANK 和 DENSE_RANK 总是确定的。排序值和紧密排序值之间的差异在于,排序代表:具有较高得分的行号加 1,而紧密排序代表:具有明显较高得分的行号加 1。从您迄今为止已经了解的内容中,您可以推导出当 ORDER BY 列表唯一时,ROW_NUMBER、RANK 和 DENSE_RANK 产生完全相同的值。
NTILE
NTILE 使您可以按照指定的顺序,将查询的结果行分散到指定数量的组 (tile) 中。每个行组都获得不同的号码:第一组为 1,第二组为 2,等等。您可以在函数名称后面的括号中指定所请求的组号,在 OVER 选项的 ORDER BY 子句中指定所请求的排序。组中的行数被计算为 total_num_rows / num_groups。如果有余数 n,则前面 n 个组获得一个附加行。因此,可能不会所有组都获得相等数量的行,但是组大小最大只可能相差一行。
SELECT speaker, track, score,
ROW_NUMBER() OVER(ORDER BY score DESC) AS rownum,
NTILE(3) OVER(ORDER BY score DESC) AS tile
FROM SpeakerStats
ORDER BY score DESC
以下为结果集:
speaker track score rownum tile
---------- ---------- ----------- ------ ----
Jessica Dev 9 1 1
Ron Dev 9 2 1
Suzanne DB 9 3 1
Kathy Sys 8 4 1
Michele Sys 8 5 2
Mike DB 8 6 2
Kevin DB 7 7 2
Brian Sys 7 8 2
Joe Dev 6 9 3
Robert Dev 6 10 3
Dan Sys 3 11 3
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐