博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从SQLSERVER/MYSQL数据库中随机取一条或者N条记录
阅读量:6956 次
发布时间:2019-06-27

本文共 2623 字,大约阅读时间需要 8 分钟。

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

很多人都知道使用rand()函数但是怎麽使用可能不是每个人都知道

建立测试表

USE [sss]GOCREATE TABLE RANDTEST(ID INT DEFAULT RAND()*100,NAME NVARCHAR(200) DEFAULT 'nihao')GOCREATE INDEX IX_RANDTEST_ID ON RANDTEST(ID)GOINSERT INTO RANDTEST DEFAULT VALUESGO 2000SELECT * FROM RANDTEST

 

第一种写法:大家会想到ORDER BY NEWID() 

SET STATISTICS TIME ON SET STATISTICS IO ONSELECT TOP 50 [id]  FROM    [dbo].[RANDTEST]GROUP BY IDORDER BY NEWID() SET STATISTICS TIME OFFSET STATISTICS IO OFF

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

 

 

 

 

第二种写法

SET STATISTICS TIME ON SET STATISTICS IO ONSELECT 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 OFFSET STATISTICS IO OFF

跟t2这个表做比较,而且每次能够达到随机取一条或者N条记录的效果

每次select出来的行数都是不一样的

 

 

比较一下IO和时间

当两种写法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 IDORDER BY RAND()*100

 

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

SELECT TOP n [id]  FROM    tableGROUP BY IDORDER 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 

转载地址:http://lpmil.baihongyu.com/

你可能感兴趣的文章
【.NET版月经问题】之二【引用类型参数就是按引用传递吗?】
查看>>
数据结构基础(20) --图的存储结构
查看>>
Metasploit相关视频
查看>>
Failed deleting my ephemeral node
查看>>
Oracle Database字符集(2)--基本概念
查看>>
fdupes 删除指定目录下重复文件
查看>>
网络嗅探软件全接触(1)
查看>>
针对binlog MIXED格式对表的增删改统计分析
查看>>
.NET简谈观察者模式
查看>>
Exchange2007中创建收件人对象、通讯组和地址列表和客户端访问
查看>>
Spring MVC Controller单例陷阱
查看>>
Azure运维系列 4:安装和使用Azure PowerShell管理云
查看>>
Java:初始化类、变量、程序块加载探讨
查看>>
在VMWare中配置SQLServer2005日志传送 Step by Step(一)——前言&预安装
查看>>
Symfony2CookBook:如何进行表单的定制渲染
查看>>
MySQL和DB2建表SQL差异
查看>>
你所不了解的静态路由特点及配置
查看>>
SQL条件查询及数据类型cast转换
查看>>
多套方案来提高python web框架的并发处理能力
查看>>
不好,两群AI打起来了!“幕后主使”是上海交大~
查看>>