从SQLSERVER/MYSQL数据库中随机取一条或者N条记录

从SQLSERVER/MYSQL数据库中随机取一条或者N条记录

不少人都知道使用rand()函数可是怎麽使用可能不是每一个人都知道数据库

创建测试表dom

USE [sss]
GO

CREATE TABLE RANDTEST(ID INT DEFAULT RAND()*100,NAME NVARCHAR(200) DEFAULT 'nihao')
GO

CREATE INDEX IX_RANDTEST_ID ON RANDTEST(ID)
GO


INSERT INTO RANDTEST DEFAULT VALUES
GO 2000

SELECT * FROM RANDTEST

 

第一种写法:你们会想到ORDER BY NEWID() 函数

SET STATISTICS TIME ON 
SET STATISTICS IO ON
SELECT TOP 50 [id]  FROM    [dbo].[RANDTEST]
GROUP BY ID
ORDER BY NEWID() 
SET STATISTICS TIME OFF
SET STATISTICS IO OFF

这种写法使用到索引扫描,并且每次select出来的结果都是同样的,都是50条记录测试

 

 

 

 

第二种写法spa

SET STATISTICS TIME ON 
SET STATISTICS IO ON
SELECT TOP 50 [t1].[ID] FROM [dbo].[RANDTEST] t1 INNER JOIN (SELECT RAND()*100 AS nid) t2 ON [t1].[ID]>[t2].[nid]
GROUP BY [t1].[ID]
SET STATISTICS TIME OFF
SET STATISTICS IO OFF

跟t2这个表作比较,并且每次可以达到随机取一条或者N条记录的效果3d

每次select出来的行数都是不同的code

 

 

比较一下IO和时间blog

当两种写法select出来的结果条数都是50条的时候,时间和IO都是同样的,若是第二种写法select出来的记录条数不是50条排序

那么IO确定比第一种写法要少索引

--第一种写法  select出来50条记录
SQL Server 执行时间:
   CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。

(50 行受影响)
表 'RANDTEST'。扫描计数 1,逻辑读取 5 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。



------------------------------------------------------------------------------


--第二种写法  select出来37条记录
SQL Server 执行时间:
   CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。

(27 行受影响)
表 'RANDTEST'。扫描计数 1,逻辑读取 4 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

SQL Server 执行时间:
   CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。

总结

若是第一种写法写成下面的样子,那么每次select出来的结果都是同样的,并且不会进行排序,在执行计划里面你看不到排序这个运算符

由于非汇集索引是排好序的,扫描非汇集索引只会获得排好序的结果

SELECT TOP 50 [id]  FROM    [dbo].[RANDTEST]
GROUP BY ID
ORDER BY RAND()*100

 

综上,想从SQLSERVER数据库中随机取一条或者N条记录时,最好把RAND()生成随机数放在JOIN子查询中以提升效率。

SELECT TOP n [id]  FROM    table
GROUP BY ID
ORDER BY NEWID()

改形成下面这个:

SELECT TOP n   [t1].[ID]  FROM table  t1 JOIN (SELECT RAND()*100 AS nid) t2 ON [t1].[ID]>[t2].[nid]
GROUP BY [t1].[ID]

就能够享受在SQL中直接取得随机数了,不用再在程序中构造一串随机数去检索了。

 

MYSQL也是一样的原理

CREATE TABLE `t_innodb_random` (
`id` INT(10) UNSIGNED NOT NULL,
`user` VARCHAR(64) NOT NULL DEFAULT '',
KEY `idx_id` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;


INSERT INTO `t_innodb_random` (`id`, `user`) VALUES('1','lily');
INSERT INTO `t_innodb_random` (`id`, `user`) VALUES('3','tom');
INSERT INTO `t_innodb_random` (`id`, `user`) VALUES('5','fancy');
INSERT INTO `t_innodb_random` (`id`, `user`) VALUES('6','cici');
INSERT INTO `t_innodb_random` (`id`, `user`) VALUES('9','syan');


SELECT * FROM t_innodb_random;


SELECT id FROM t_innodb_random ORDER BY RAND() LIMIT 5;
-- 改形成下面这个:

SELECT id FROM t_innodb_random t1 INNER JOIN (SELECT RAND()*10 AS nid) t2 ON t1.id > t2.nid LIMIT 5;

 ---------------------------------------------------------------------------------------------

 

若有不对的地方,欢迎你们拍砖o(∩_∩)o 

相关文章
相关标签/搜索