微软BI开拓者数据库专区SQL Server开发 找到第N个最大或最小的记录的有效方法

1  /  1  页   1 跳转 查看:4163

[技术文档] 找到第N个最大或最小的记录的有效方法

找到第N个最大或最小的记录的有效方法

找到第N个最大或最小的记录的有效方法

--王成辉翻译整理,转贴请注明出自微软BI开拓者www.windbi.com
--
原帖地址

我们经常需要从记录集里找到第N个(第五或第八或第十)最大或最小的记录。在Oracle和MSSQL里的方法有所不同,因为在Oracle可以用RowNum。

一段时间以前我在一个超过2亿条记录有56个varchar列和一个int列的大表上要实现同样的问题。我试了不同的解决方法(从网上找到的),但性能都非常差。

于是我决定着手去找到这个问题更有效的解决方法。



CREATE TABLE [Risk] (
[Col001] [varchar] (200) NULL ,
[Col002] [varchar] (200)  NULL ,
[Col003] [varchar] (10) NULL,
[RowNum_Risk] [int] IDENTITY (1, 1) NOT NULL ,
CONSTRAINT [PK_risk] PRIMARY KEY  CLUSTERED
(
  [RowNum_Risk]
)  ON [PRIMARY]
) ON [PRIMARY]


现在让我们向表里插入一些记录:

INSERT INTO Risk Values('AAA1','BBB1','CCC1',1);
INSERT INTO Risk Values('AAA2','BBB2','CCC2',2);
INSERT INTO Risk Values('AAA3','BBB3','CCC3',3);
INSERT INTO Risk Values('AAA4','BBB4','CCC4',4);
INSERT INTO Risk Values('AAA5','BBB5','CCC5',5);
INSERT INTO Risk Values('AAA6','BBB6','CCC6',6);
INSERT INTO Risk Values('AAA7','BBB7','CCC7',7);
INSERT INTO Risk Values('AAA8','BBB8','CCC8',8);
INSERT INTO Risk Values('AAA9','BBB9','CCC9',9);
INSERT INTO Risk Values('AAA10','BBB10','CCC10',10);


查询如下:

SELECT Col001,Col002,Col003,RowNum_Risk FROM Risk
WHERE RowNum_Risk = (SELECT MIN(RowNum_Risk) FROM (SELECT DISTINCT TOP 5 RowNum_Risk FROM Risk ORDER BY RowNum_Risk DESC)B)


查询将返回表的第五个最大的记录。如果你想找第八个或第十个或任意一个最大的记录,把5替换为你想要的数字即可。

现在让我们看看执行计划。

MSSQL为“SELECT DISTINCT TOP 5 RowNum_Risk FROM Risk ORDER BY RowNum_Risk DESC”使用索引扫描去得到第N条记录。

然后为外部查询使用索引搜索去产生结果。

结论:

这是我发现从MSSQLServer的大表里找到第N个最大或最小记录的最好的方法。然而当你试图从数据集里找到比方说第1百万条最大的记录,那么查询计划时间将更长。但都在数分钟内能完成而不是在数小时之内。
虽有智慧,不如乘势;虽有鎡基,不如待时。
君子学以聚之,问以辨之,宽以居之,仁以行之。
独学而无友,则孤陋而寡闻。
 

回复: 找到第N个最大或最小的记录的有效方法

学会了,大师
 
1  /  1  页   1 跳转

版权所有 微软BI开拓者 

Powered by Discuz!NT 2.1.202    Copyright © 2001-2012 Comsenz Inc.
Processed in 0.0468768 second(s) , 5 queries.
返顶部