背景:想在表中随机取10条记录,让取出来的数据不重复(表中必须是有个递增列,且递增从1开始间隔为1)。 

数据表:

CREATE TABLE testable
(
id INT  IDENTITY(1,1),
myname  NVARCHAR(1000),
insertedTime DATETIME DEFAULT SYSDATETIME()
)

 

表中共有100条数据,如下

省略……

 

 

 

 

1.     首先想到的是MSSQL自带的newid()

 

采用这种方法时,需要将表中所有记录与newid()生成的值进行比较从而进行排序。因此,如果表中的记录较多,操作会非常缓慢。

 

 

 


USE  Gift163DB
go

SELECT  TOP  14  * FROM  dbo.testable   ORDER BY NEWID()


 

缺点:1. 取出的10条数据会出现重复      2.当数据表数据很多的时候,速度将很慢 (每次重新计算newid)

 

 

 

2. 自定义函数返回一个表,表中记录的是随机生成的N个id值。

 

1)rand()生成随机数        rand()*count,CEILING,floor用法 

2)如果临时表中无此数据,则放入,否则重新生成

3)直到N条记录已经生成

 

注意:标量函数function内不能出现rand()方法,变通下生成个view  v_random,然后在函数内调用 v_random获取随机数

create view v_random
AS

   select CEILING(rand()*51) as random    --注意51,生成的是1到51之间的数字,因为事先知道数据库中有51条记录
go

 

 

自定义函数代码如下:

 

ALTER FUNCTION  randomIntStringWithCommaSplit(@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为临时表的唯一列)

 

 

最后通过  select * from table  where id in  randomIntStringWithCommaSplit(10) ,这样就可以从table中随机取出10条不重复的数据来了。

 

 

 

 

3.存储过程取不重复的数据

 

--dbo.getRandomDataFromTable

--输入参数  @tableName  nvarchar(100),--表名

---@dataCount  nvarchar(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]
@tableName  nvarchar(100),
@dataCount  nvarchar(100)
AS
BEGIN
  --SET NOCOUNT ON;

    DECLARE @t TABLE (id INT)   --临时表
    DECLARE @i  INT             --临时变量
    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
            from  sysobjects
           where  id = object_id('testable')
            and   type = 'U')
   drop table testable
go

CREATE TABLE testable
(
id INT  IDENTITY(1,1),
myname  NVARCHAR(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
 exec    getRandomDataFromTable  'testable',10


 

 

 

自定义的存储过程不会出现重复的记录

 

 

 

 

 

4.改进的存储过程,最终存储过程

 

输入参数3个:表名,表的递增列名 , 要取的N条数据

 

USE Gift163DB
GO
IF OBJECT_ID ( 'dbo.getRandomDataFromTable', 'P' ) IS NOT NULL
    DROP PROCEDURE dbo.getRandomDataFromTable;
GO

CREATE PROC  [dbo].[getRandomDataFromTable]
@tableName  nvarchar(100),
@identityKey NVARCHAR(100),
@dataCount  nvarchar(100)
AS
BEGIN
  --SET NOCOUNT ON;

    --DECLARE @t TABLE (id INT)   --临时表
    DECLARE @i  INT             --临时变量
    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条数据

 

最终的存储过程不管你随机取多少条数据(只要每次取的数据数目小于表中行数) 就可以保证每次取的数据不会重复。当然前提是,取的表必须有个递增列,而且以1开始,递增1.

sql 生成随机数 以及不重复随机数的更多相关文章

  1. 动态生成16位不重复随机数、随机创建2位ID

    /** 1. * 动态生成16位不重复随机数 * * @return */ public synchronized static String generate16() { StringBuffer ...

  2. js【生成规定数量不重复随机数】、【冒泡排序】、【鸡尾酒排序】、【选择排序】、【插入排序】、【未完工的二分插入排序】------【总结】

    [生成规定数量不重复随机数] function creatRandom( num ){ var randomLen = num, ranArr = [], thisRan = null, whileO ...

  3. sql 生成某个范围内的随机数

    从i-j的范围内的随机数,那么公式为FLOOR(i+RAND()*(j-i+1))

  4. SQL - 生成指定范围内的随机数

    今天按照公司需求,需要做一个sql作业来对数据库定时触发,其中有个难点,就是在sql中需要在1-n中随机出来一个结果. google了半天,找到一个比较好的方式. 写下这个sql: DECLARE @ ...

  5. 【转】 SQL - 生成指定范围内的随机数

    DECLARE @Result INT DECLARE @Upper INT DECLARE @Lower INT SET @Lower = 1 SET @Upper = 10 SELECT @Res ...

  6. Java数组实现随机生成N-M之间不重复的随机数

    接收一个整形数组,使用Math.Random每次在规定的数字范围内随机产生数字,然后嵌套for循环依次判断是否有重复值,如果有既外循环变量减一,直到把数组装满为止. /** * 随机生成 N--M的不 ...

  7. C#生成不重复随机数列表

    C#生成不重复(随机数 http://www.jbxue.com/tags/suijishu.html)列表实例的代码.例子: ;             Random rnd = ; i <  ...

  8. PHP函数:生成N个不重复的随机数

    思路:将生成的随机数存入数组,再在数组中去除重复的值,即可生成一定数量的不重复随机数. 程序: <?php /* * array unique_rand( int $min, int $max, ...

  9. [转载]C# Random 生成不重复随机数

    Random 类 命名空间:System 表示伪随机数生成器,一种能够产生满足某些随机性统计要求的数字序列的设备. 伪随机数是以相同的概率从一组有限的数字中选取的.所选数字并不具有完全的随机性,因为它 ...

随机推荐

  1. 常用的SQLalchemy 字段类型

    https://blog.csdn.net/weixin_41896508/article/details/80772238 常用的SQLAlchemy字段类型 类型名 python中类型 说明 In ...

  2. [转载]js复制内容加版权声明代码

    转自:https://www.cnblogs.com/zdz8207/p/js-oncopy.html var ua = navigator.userAgent.toLowerCase(); if( ...

  3. java配置文件properties,yml,一般文件

    JAVA编写配置文件的几种方式: JAVA配置文件,一般都放在resource目录下,无论是下面提到的properties.yml还是普通的txt等文件. 在打成jar包之后,只需要jar包程序就可运 ...

  4. Pandas 之 过滤DateFrame中所有小于0的值并替换

    Outline 前几天,数据清洗时有用到pandas去过滤大量数据中的“负值”: 把过滤出来的“负值”替换为“NaN”或者指定的值. 故做个小记录. 读取CSV文件 代码: import pandas ...

  5. make编译六

    如果要使用隐含规则生成你需要的目标,你所需要做的就是不要写出这个目标的规则.那么,make 会试图去自动推导产生这个目标的规则和命令,如果make 可以自动推导生成这个目标的规则和命令,那么这个行为就 ...

  6. DBA学习参考绝佳资料

    原文来自:pursuer.chen 原文地址:https://www.cnblogs.com/chenmh/default.aspx?page=1 [置顶]MongoDB 文章目录 2018-02-0 ...

  7. url监控

    #!/usr/bin/env python #coding:utf-8 import MySQLdb,requests import time from datetime import datetim ...

  8. Xamrin开发安卓笔记(三)

    http://www.cnblogs.com/minCS/p/4118170.html Xamrin开发安卓笔记(三)   安装片 Xamrin开发安卓笔记(一) Xamrin开发安卓笔记(二) 这次 ...

  9. java实现简单邮件的发送以及常见问题

    java实现简单邮件的发送以及常见问题 最近遇到个需求需要实现发送邮件的功能,以前做发送邮件功能都是有邮箱用户名密码,通过用户名密码连接对应的SMTP服务器来实现邮件的发送.但是这次用公司内部的邮箱, ...

  10. 2018 ACM 国际大学生程序设计竞赛上海大都会 F - Color it (扫描线)

    题意:一个N*M的矩形,每个点初始都是白色的,有Q次操作,每次操作将以(x,y)为圆心,r为半径的区域涂成黑点.求最后剩余白色点数. 分析:对每行,将Q次操作在该行的涂色视作一段区间,那么该行最后的白 ...