sql 生成随机数 以及不重复随机数
2015-11-07 16:33
375 查看
背景:想在表中随机取10条记录,让取出来的数据不重复(表中必须是有个递增列,且递增从1开始间隔为1)。数据表:CREATE TABLE testable(id INTIDENTITY(1,1),mynameNVARCHAR(1000),insertedTime DATETIME DEFAULT SYSDATETIME())表中共有100条数据,如下
省略……![](http://images.cnitblog.com/blog/117912/201403/282332385479905.png)
最后通过select * from tablewhere id inrandomIntStringWithCommaSplit(10) ,这样就可以从table中随机取出10条不重复的数据来了。
自定义的存储过程不会出现重复的记录4.改进的存储过程,最终存储过程输入参数3个:表名,表的递增列名 , 要取的N条数据
最终的存储过程不管你随机取多少条数据(只要每次取的数据数目小于表中行数) 就可以保证每次取的数据不会重复。当然前提是,取的表必须有个递增列,而且以1开始,递增1.昂首阔步,不留一点遗憾
![](http://images.cnitblog.com/blog/117912/201403/300057192198212.png)
1. 首先想到的是MSSQL自带的newid()
采用这种方法时,需要将表中所有记录与newid()生成的值进行比较从而进行排序。因此,如果表中的记录较多,操作会非常缓慢。![](http://images.cnitblog.com/blog/117912/201403/282332385479905.png)
USEGift163DB
go
SELECTTOP14* FROMdbo.testable ORDER BY NEWID()缺点:1. 取出的10条数据会出现重复2.当数据表数据很多的时候,速度将很慢 (每次重新计算newid)
2. 自定义函数返回一个表,表中记录的是随机生成的N个id值。
1)rand()生成随机数rand()*count,CEILING,floor用法2)如果临时表中无此数据,则放入,否则重新生成3)直到N条记录已经生成注意:标量函数function内不能出现rand()方法,变通下生成个viewv_random,然后在函数内调用 v_random获取随机数create view v_random
AS
select CEILING(rand()*51) as random--注意51,生成的是1到51之间的数字,因为事先知道数据库中有51条记录
go自定义函数代码如下:
ALTER FUNCTIONrandomIntStringWithCommaSplit(@counts int) –counts 表明返回的个数
RETURNS @t TABLE (filed1 int)--返回表@t,有个int类型的 field列
AS
BEGIN
DECLARE @randomInt INT
DECLARE @i INT
SET @i=0
WHILE @i<@counts
BEGIN
select @randomInt= random FROM v_random
--不能是 SET @randomInt=SELECT random FROM v_random
IF NOT EXISTS(SELECT TOP 1 * FROM @t WHERE filed1=@randomInt)
BEGIN
INSERT INTO @t VALUES (@randomInt)
SET @i=@i+1
END
END
RETURN
END上面函数返回的是一个表类型,表中有个int字段,存放要查找的N个不同的keyId(keyId为要查找表的递增列,且递增为1,从1开始递增)所以返回的表中存放的数据是 dbo.Articles中的id列的值。使用:调用上面的自定义函数返回10个不重复的id
SELECT * FROM randomIntStringWithCommaSplit(10)下面是几次的执行结果,可以看到每个结果中都不存在重复的值(fidled1为临时表的唯一列)
![](http://images.cnitblog.com/blog/117912/201403/282332495165255.png)
![](http://images.cnitblog.com/blog/117912/201403/282332531561908.png)
![](http://images.cnitblog.com/blog/117912/201403/282332572345962.png)
![](http://images.cnitblog.com/blog/117912/201403/282333011253774.png)
![](http://images.cnitblog.com/blog/117912/201403/282333115005238.png)
3.存储过程取不重复的数据
--dbo.getRandomDataFromTable--输入参数@tableNamenvarchar(100),--表名---@dataCountnvarchar(100)--取N条数据输出结果集:列id,存放N条要查询的数据USE Gift163DB
GO
IF OBJECT_ID ( 'dbo.getRandomDataFromTable', 'P' ) IS NOT NULL
DROP PROCEDURE dbo.getRandomDataFromTable;
GO
CREATE PROC[dbo].[getRandomDataFromTable]
@tableNamenvarchar(100),
@dataCountnvarchar(100)
AS
BEGIN
--SET NOCOUNT ON;
DECLARE @t TABLE (id INT) --临时表
DECLARE @iINT --临时变量
DECLARE @randomInt INT--每次随机生成的整数
DECLARE @tableCount INT --表的行数
--先获取表中最大数据的id
EXEC('SELECT '+@tableCount+'=COUNT(*) FROM'+@tableName+'')
SET @i=0
WHILE @i<@dataCount
BEGIN
SELECT @randomInt=CEILING(RAND()*@tableCount)
IF NOT EXISTS(SELECT TOP 1 * FROM @t)
BEGIN
INSERT INTO @t VALUES (@randomInt)
SET @i=@i+1
END
END
--打印出取出的表的id
SELECT * FROM @t
END
Go生成测试数据100条
USE Gift163DB
GO
if exists (select 1
fromsysobjects
whereid = object_id('testable')
and type = 'U')
drop table testable
go
CREATE TABLE testable
(
id INTIDENTITY(1,1),
mynameNVARCHAR(1000),
insertedTime DATETIME DEFAULT SYSDATETIME()
)
//插入100条数据
DECLARE @i INT
SET @i=1
WHILE @i<100
BEGIN
INSERT INTO tesTable (myname) VALUES ('我的名字是'+CONVERT(NVARCHAR, @i) ) --将 varchar 值 '我的名字是' 转换成数据类型 int 时失败。
SET @i=@i+1
End调用上面的存储过程从表testable取10条不重复id
USE Gift163DB
go
execgetRandomDataFromTable'testable',10
![](http://images.cnitblog.com/blog/117912/201403/300057202193040.png)
![](http://images.cnitblog.com/blog/117912/201403/300057210944139.png)
![](http://images.cnitblog.com/blog/117912/201403/300057218917496.png)
USE Gift163DB
GO
IF OBJECT_ID ( 'dbo.getRandomDataFromTable', 'P' ) IS NOT NULL
DROP PROCEDURE dbo.getRandomDataFromTable;
GO
CREATE PROC[dbo].[getRandomDataFromTable]
@tableNamenvarchar(100),
@identityKey NVARCHAR(100),
@dataCountnvarchar(100)
AS
BEGIN
--SET NOCOUNT ON;
--DECLARE @t TABLE (id INT) --临时表
DECLARE @iINT --临时变量
DECLARE @randomInt INT--每次随机生成的整数
DECLARE @tableCount INT --表的行数
--先获取表中最大数据的id
DECLARE @str NVARCHAR(3000)
SET @str='SELECT @tableCount=COUNT(*) FROM'+@tableName
exec sp_executesql @str, N'@tableCount int output', @tableCount output
create TABLE #sdf (id int)
SET @i=0
WHILE @i<@dataCount AND @i<@tableCount
BEGIN
SELECT @randomInt=CEILING(RAND()*@tableCount)
IF NOT EXISTS(SELECT TOP 1 * FROM #sdf WHERE id=@randomInt)
BEGIN
INSERT INTO #sdf VALUES (@randomInt)
SET @i=@i+1
END
END
--取出数据
DECLARE @str2 NVARCHAR(2000)
SET @str2=' SELECT* FROM '+@tableName
+' where '+@identitykey
+' in '
+' (select id from #sdf )'
PRINT @str2
--select id from@t
EXEC (@str2)
--exec sp_executesql @str2,N'@t TABLE',@t OUTPUT
END调用存储过程:随机取10条数据
![](http://images.cnitblog.com/blog/117912/201403/300057236568222.png)
![](http://images.cnitblog.com/blog/117912/201403/300057246879508.png)
相关文章推荐
- SQL server的增删改查练习
- mysql使用过程中碰到的问题
- Scala 各种数据库访问框架简介
- centos6.5环境下redis3.0集群搭建和配置
- MySQL忘记密码怎么办
- 修改mysql DataDir方式
- Linux 下安装Redis教程
- 基于MySQL5.7MHA的配置
- PHP-Redis扩展使用手册(三)
- 【回顾整理】暴走的SQL语句练习!!!
- Windows下Mysql解压缩版配置安装与卸载
- sql子句的执行顺序
- 在LiftWeb下配置PostgreSQL数据库
- 如何给web项目添加redis服务 JAVA几种缓存技术 ehcache和redis哪个更好
- jsp程序向调用mysql语句操作数据库传中文出现乱码
- mysql中的关键字
- 通过innobackupex实现对MySQL的完整热备份
- 在ionic 项目中 使用sqlite 代替local storage
- SQL Server 2008 R2——以特定符号出现的次数来判断当前内容所在的层次
- Oracle安装图解