• sql 生成随机数 以及不重复随机数


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

    数据表:

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

    表中共有100条数据,如下

    image 省略……

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

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

    image

    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为临时表的唯一列)

    image image image image image

    最后通过  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
    

    image image image

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

    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条数据

    image image

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

  • 相关阅读:
    C#操作Word (2)-- 打开&关闭Word文档
    JS input 银行卡号格式转换
    解决H5在微信浏览器或QQ浏览器修改title的问题
    CSS
    Atom 编辑器使用和学习
    php的一个小坑,输出不了json_encode
    js 组合键监听ctrl + enter
    webpack3.0 环境搭建
    css 使表格随着内容自动适应宽度
    获取input光标的x和y轴
  • 原文地址:https://www.cnblogs.com/StudyLife/p/3631954.html
Copyright © 2020-2023  润新知