背景:想在表中随机取10条记录,让取出来的数据不重复(表中必须是有个递增列,且递增从1开始间隔为1)。
数据表:dbo.Articles
( id int identity(1,1) int not null
title nvarchar(100),
context nvarchar(1000)
)
1. 首先想到的是MSSQL自带的newid()
采用这种方法时,需要将表中所有记录与newid()生成的值进行比较从而进行排序。因此,如果表中的记录较多,操作会非常缓慢。
select top 10 * from dbo.Articles order by newid()
每次一批记录是随机取出。但是同一批数据有重复的数据,比如上面的2个热点。
缺点:1. 取出的10条数据会出现重复 2.当数据表数据很多的时候,速度将很慢
2. 自定义函数生成一个表。通过rand()函数随机生成最大记录keyid以内的记录,并放入表中,最后函数返回表类型
注意:标量函数function内不能出现rand()方法,变通下生成个view v_random,然后在函数内调用 v_random获取随机数
create view v_randomASselect CEILING(rand()*51) as random --注意51,生成的是1到51之间的数字,因为事先知道数据库中有51条记录go
自定义函数代码如下:
ALTER FUNCTION randomIntStringWithCommaSplit(@counts int) –counts 表明返回的个数RETURNS @t TABLE (filed1 int) --返回表@t,有个int类型的 field列ASBEGINDECLARE @randomInt INTDECLARE @i INTSET @i=0WHILE @i<@countsBEGINselect @randomInt= random FROM v_random--不能是 SET @randomInt=SELECT random FROM v_random
IF NOT EXISTS(SELECT TOP 1 * FROM @t WHERE filed1=@randomInt)BEGININSERT INTO @t VALUES (@randomInt)SET @i=@i+1ENDENDRETURNEND
上面函数返回的是一个表类型,表中有个int字段,存放要查找的N个不同的keyId (keyId为要查找表的递增列,且递增为1,从1开始递增)
所以返回的表中存放的数据是 dbo.Articles中的id列的值。
使用:调用上面的自定义函数返回10个不重复的id
SELECT * FROM randomIntStringWithCommaSplit(10)
下面是几次的执行结果,可以看到每个结果中都不存在重复的值
本篇用到的函数与知识
1. FLOOR(numeric_expression)返回小于或等于数值表达式的最大整数。
print floor (1.4) ,结果是1
print floor (1.8),结果也是1
2. CEILING(numeric_expression) 返回大于或等于数值表达式的最小整数。
print floor (1.4) ,结果是2
print floor (1.8),结果也是2