`

如何快速生成100万不重复的8位编号

 
阅读更多

最近在论坛看到有人问,如何快速生成100万不重复的8位编号,对于这个问题,有几点是需要注意的:

1. 如何生成8位随机数,生成的数越随机,重复的可能性当然越小

2. 控制不重复

3. 考虑性能

针对这个问题,我写了如下的示例来解决,希望能为有这类需求的人提供指导

生成100万条8位不重复数据的示例

USE tempdb

GO

-- 创建测试表

CREATE TABLE tb(id char(8))

-- 创建用于自动过滤重复值的唯一索引

CREATE UNIQUE INDEX IX_tb ON tb(id)

WITH IGNORE_DUP_KEY

GO

-- 测试数据插入的处理时间, 记录开始处理的时间点

DECLARE @dt datetime

SET @dt = GETDATE()

-- 插入随机数据

SET NOCOUNT ON

DECLARE @row int

SET @row = 1000000 -- 设置总记录数

WHILE @row >0

BEGIN

-- 显示提示信息, 表示还需要插入多行数据

RAISERROR('need %d rows', 10, 1, @row) WITH NOWAIT

-- 插入随机的位编码数据

SET ROWCOUNT @row

INSERT tb SELECT

id = RIGHT(100000000 + CONVERT(bigint, ABS(CHECKSUM(NEWID()))), 8)

FROM syscolumns c1, syscolumns c2

SET @row = @row - @@ROWCOUNT

END

-- 显示插入数据使用的时间

SELECT BeginDate = @dt, EndDate = GETDATE(),

Second = DATEDIFF(Second, @dt, GETDATE()),

GO

-- 显示最终的结果记录是否正确

SELECT COUNT(*) FROM tb

GO

-- 删除测试

DROP TABLE tb

解决中用到的技巧:

1. 控制产生的数据不重复,直接使用唯一索引中的 IGNORE_DUP_KEY 选项,使插入数据中的重复值自动过滤,避免手工处理重复

2. 使用 CHECKSUM 配合 NEWID() 函数,使生成的数据尽量随机,一般生成随机数会考虑使用 RAND() 函数,但这个函数是产生伪随机值,用下面的语句测试一下,会发现产生的数据全部是一样的,这不适用于想批量生成多个随机数,而NEWID() 函数生成的是GUID,基本上不会有重复的,再通过CHECKSUM将其转化成数字,这样产生重复的可能性会比较小

SELECT TOP 10

<place w:st="on"><span style="COLOR: fuchsia">RAND</span></place>()

FROM sysobjects

3. 在效率控制,使用循环+批量生成的方式,而不是传统的逐个生成。在SQL Server中,每个插入语句都会有一个内部的事务处理,如果逐条插入,则事务的开销太大,效率势必非常低;不考虑一次性生成100万数据,一则因为生成的数据可能有重复的,去掉重复就没有100万了,二则一次性生成100万数据,消耗的内存和CPU资源也很高,一般的电脑可能承受不住



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1099215


<script src="http://localhost:82/PromoteIcon.aspx?id=1099215" type="text/javascript"></script> [收藏到我的网摘] 邹建发表于 2006年08月20日 11:28:00
<link href="http://blog.csdn.net/zjcxc/Services/Pingback.aspx" rel="pingback"> <!--<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"xmlns:dc="http://purl.org/dc/elements/1.1/"xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"><rdf:Descriptionrdf:about="http://blog.csdn.net/zjcxc/archive/2006/08/20/1099215.aspx"dc:identifier="http://blog.csdn.net/zjcxc/archive/2006/08/20/1099215.aspx"dc:title="如何快速生成100万不重复的8位编号"trackback:ping="http://tb.blog.csdn.net/TrackBack.aspx?PostId=1099215" /></rdf:RDF>--><script type="text/javascript">function hide(){showComment();}</script>



特别推荐:
<script type="text/javascript">document.write("<img src=http://counter.csdn.net/pv.aspx?id=24 border=0 width=0 height=0>");</script>

#atomic_age发表于2006-08-21 21:54:00IP: 211.100.21.*
TrackBack来自《如何快速生成100万不重复的8位编号?》

如何快速生成100万不重复的8位编号

#seLecT.发表于2006-08-24 17:35:00IP: 211.100.21.*
TrackBack来自《如何快速生成100万不重复的8位编号》

如何快速生成100万不重复的8位编号

#醉梦流仙发表于2006-08-21 15:53:00IP: 218.107.55.*
“如何快速生成100万不重复的8位编号”
不是我要钻牛角尖,这个要求,数字0-1000000也满足要求啊,呵呵,如果不特别说明的话。

#是劫是缘发表于2006-08-21 18:29:00IP: 221.226.115.*
感觉很搞笑,不知道楼主想说什么?
请问楼主,示例执行了多长时间?

#qiandeng发表于2006-08-21 18:43:00IP: 222.66.38.*
这个还是实用的,很多时候需要的是真正随机

#allyesno发表于2006-08-21 18:54:00IP: 59.34.142.*
如果是验证码0-100000也行了 只要加上干扰信息

#atomic_age发表于2006-08-21 21:37:00IP: 221.200.164.*
我给个方法。
假设我要产生从10000000 - 99999999妈即在产生一百的随机数。可以建立一个表table1,这个表有两个字段,一个是所产生的随机数字段(int型),另外一个是和这个字段同类型的字段。
使用9999999 - 1000000 =89999999 整除 9 = 89(舍去)。然后从10000000开始循环1000000次,从10000000开始每一次加89,
即10000000、10000089、10000178...
然后每循环一次,使用newid生成一个随即数,将这两个数做为值插入tabl1中。这样,table1就有1百万条记录了,不过是随机值是顺序的。但由于第二个字段是随机的,因此,只要按第二个字段排序,第一个字段上的值就是随机的。

这样做不用检查重复值就可以保证得到1000000个无重复的随机数。而且它们是均匀分布在10000000到99999999之间。
当然,也可以随机变化89的步长,使其更加随机。
这样做还有一个好处,可以分批地生成记录,然后一起插入表中。如一次产生1000条这样的记录,插入后再产生下一条记录。这样只要循环1000次就可完成。

如果这个方法有什么问题可以通过asklining@126.com和我联系。

#atomic_age发表于2006-08-21 21:39:00IP: 221.200.164.*
我给个方法。
假设我要在10000000 - 99999999之间产生一百万个不重复的随机数。可以建立一个表table1,这个表有两个字段,一个是所产生的随机数字段(int型),另外一个是和这个字段同类型的字段。
使用9999999 - 1000000 =89999999 整除 9 = 89(舍去)。然后从10000000开始循环1000000次,从10000000开始每一次加89,
即10000000、10000089、10000178...
然后每循环一次,使用newid生成一个随即数,将这两个数做为值插入tabl1中。这样,table1就有1百万条记录了,不过是随机值是顺序的。但由于第二个字段是随机的,因此,只要按第二个字段排序,第一个字段上的值就是随机的。

这样做不用检查重复值就可以保证得到1000000个无重复的随机数。而且它们是均匀分布在10000000到99999999之间。
当然,也可以随机变化89的步长,使其更加随机。
这样做还有一个好处,可以分批地生成记录,然后一起插入表中。如一次产生1000条这样的记录,插入后再产生下一条记录。这样只要循环1000次就可完成。

如果这个方法有什么问题可以通过asklining@126.com和我联系。

#lance发表于2006-08-21 23:07:00IP: 60.232.165.*
用个循环 把数组打乱,效果是不是也一样?

#myan发表于2006-08-21 22:28:00IP: 219.236.56.*
楼主是数据库专家,用数据库的方法来解决问题是无可厚非。如果让我来做的话,我会用STL里的shuffle算法来做。对于100万这样的规模来说,应该是轻而易举的。

#atomic_age发表于2006-08-22 08:40:00IP: 218.25.53.*
哈哈,上面写的有些bug

假设我要在10000000 - 99999999之间产生100万个不重复的随机数。可以建立一个表table1,这个表有两个字段,一个是所产生的随机数字段(int型),另外一个也是int型字段。
使用99999999 - 10000000 =89999999 整除 1000000 = 89(舍去)。然后从10000000开始循环1000000次,从10000000开始每一次加89,
即10000000、10000089、10000178...
然后每循环一次,使用newid生成一个随机数,将这两个数做为值插入table1中。即第一个字段插入按步长89递增的数,第二个数是使用newid随机生成的数。这样,table1就有100万条记录了,不过随机值是顺序的。但由于第二个字段是随机的,因此,只要按第二个字段排序,第一个字段上的值就是随机的。

这样做不用检查重复值就可以保证得到1000000个无重复的随机数。而且它们是均匀分布在10000000到99999999之间。
当然,也可以随机变化89的步长,使其更加随机。
这样做还有一个好处,可以分批地生成记录,然后一起插入表中。如一次产生1000条这样的记录,插入后再产生下一千条记录。这样只要循环1000次就可完成。

至于代码,很简单,自己写吧,这里只给出思路!!

#brucesea发表于2006-08-22 12:43:00IP: 210.94.41.*
用Knuth Shuffle算法很容易的。

#kill发表于2006-10-16 15:33:00IP: 124.89.87.*
NB

#ADANDELION发表于2006-10-19 21:21:00IP: 218.81.211.*
http://community.csdn.net/Expert/topic/4960/4960404.xml?temp=3.658694E-02

问题是O提的.
谢谢邹老大,确实厉害.

#tfe发表于2006-11-27 13:26:00IP: 58.63.39.*
邹老大,我有个问题请教一下。
我现在要生成18位随机数。
用你这个程序跑了后,发现很多不够18位的数。
我可以怎么样在这里加个较验,同时又能高效的写入表里

#tfe发表于2006-11-27 16:42:00IP: 58.63.39.*
另外还有个问题就是这个程序不能多次运行。批量写入时,只要有一条重了,整批都写不进去。我写到60万条出错,再想加,就基本上写不入了。而且我是18位。

#cuixiping发表于2007-04-13 16:27:54IP: 125.77.158.*
我自己也写了一篇,与邹大哥的思路不一样:
[原创] 生成X个不重复的Y位长度的随机数
http://blog.csdn.net/cuixiping/archive/2007/04/13/1563708.aspx

邹大哥去指点指点吧。

我用邹建大哥的上面代码在查询分析器里面会报语法错误啊!
我的sqlserver 2000.


#cuixiping发表于2007-04-13 16:29:04IP: 125.77.158.*
我的blog里面不能换行,我把我写的帖在这里吧。

/*
[原创] 生成X个不重复的Y位长度的随机数
by cuixiping(无心) 2007-04-13
(经测试,速度还可以。改成存储过程也很容易,我就偷懒不写了。)
*/
declare @X int; /* 要获取的个数 */
declare @Y tinyint; /* 要获取的长度,越大越慢 */
declare @i int;
declare @j bigint;
declare @SQL1 varchar(1000);
declare @SQL2 varchar(1000);
declare @SQL3 nvarchar(2000);
set @X=100;
set @Y=6; /* 10的@Y次方必须大于@X。且@Y不要太大,否则会很慢,量“机”而为 */
set @i=2;
set @j=10;

USE tempdb
-- 创建测试表及其数据
if exists (select 1 from sysobjects where name = 'T' and type = 'U')
drop table T;
CREATE TABLE T(n tinyint);
INSERT INTO T SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
UNION ALL SELECT 0
;
-- 组装语句
set @SQL1='select top '+ CAST(@X AS varchar) +' t1.n * '+ CAST(POWER(@j,@Y-1) AS varchar);
set @SQL2=' as nn from T t1';
WHILE @i<=@Y
BEGIN
set @SQL1 = @SQL1 + '+t' + CAST(@i AS varchar) + '.n*'+ CAST(POWER(@j,@Y-@i) AS varchar);
set @SQL2 = @SQL2 + ',T t' + CAST(@i AS varchar);
set @i=@i+1;
END
set @SQL3 = @SQL1 + @SQL2 + ' where t1.n>0 order by newid()';
-- 执行语句
EXEC sp_executesql @SQL3;
-- 删除测试
DROP TABLE T;
分享到:
评论

相关推荐

    基于Java实现自动生成四则运算【100012409】

    自动生成 10 道 100 以内的 2 个操作数的四则运算算式(+ - * /),要求运算结果也在 100 以内,把运算式存入“result.txt”文件中。题目数量、数字范围、操作数和运算规则是可控的。 使用-n 参数控制生成题目的个数...

    《Excel应用大全》示例文件 光盘文件

    • 利用MID 函数提取身份证号码中的8 位生日数字 • 使用文本提取函数进行数字分列 • 使用查找函数拆分空格分隔的数据 • 实现EAN-13条码的校验位的算法 • 利用文本查找函数进行模糊查找 • 利用SEARCHB 函数分离...

    Excel函数活用范例大辞典(全新版).何先军.2015-2(带书签高清文字版).pdf

    213 根据产品名称的拼音生成产品编号 410 214 根据本月收入查询应采用税率和速算扣除数 413 215 查找某销售员某月的销售业绩 415 216 制作员工工牌 416 217 查询最后入职的员工 418 218 查询某员工是否...

    EXCEL集成工具箱V8.0完整增强版(精简)

    作了18个分类, 而在函数向导对话框中也生成100个左右新的函数,用于扩展Excel的计算功能。且所有功能都通用于 Excel 2002、2003和2007、2010。支持中英文显示与繁简体操作系统、拥有20多款华丽的皮肤界面,支持Excel...

    文章管理系统

    2.列表页导航分页加入超过100分页时,下拉选择自动变成文本框输入,防止下拉项太多而影响速度 3.纠正文章管理因异常栏目信息,而造成页面错误 4.生成的缓存文件加入和%&gt;字符的编码,防止因配置内容含asp代码而造成...

    EXCEL集成工具箱V6.0

    作了18个分类, 而在函数向导对话框中也生成100个左右新的函数,用于扩展Excel的计算功能。且所有功能都通用于 Excel 2002、2003和2007、2010。支持中英文显示与繁简体操作系统、拥有20多款华丽的皮肤界面,支持Excel...

    FMLDATA的源码

    其中, XXXXXX为股票代码,如深发展为000001等,由于沪市指数代码与深市股票代码重复,所以沪市指数代码在原代码前加1,例如上证综指为000001,则这里的XXXXXX为1000001(7位);N是编号,由用户自己指定,应为大于0...

    51单片机C语言编程基础及实例

    如果将一个 16 位二进数赋给一个 8 位的字节变量,则自动截断为低 8 位,而丢掉高 8 位。 ++var 表示对变量 var 先增一;var—表示对变量后减一。 x |= 0x0f;表示为 x = x | 0x0f; 高四位。 6. While( 1 ); 表示...

    JAVA上百实例源码以及开源项目源代码

    8个目标文件 简单 JavaScript万年历 显示出当前时间及年份,还可以选择年份及月份和日期 Java编写的HTML浏览器 一个目标文件 摘要:Java源码,网络相关,浏览器  Java编写的HTML浏览器源代码,一个很简单甚至不算是...

    C#程序开发范例宝典(第2版).part13

    精选570个典型范例,全面覆盖实用和热点技术,涉及面广,实用性强源于实际项目开发,帮助读者短时间掌握更多实用技术,提高编程水平范例经过精心编排,重点、难点突出,易学易懂书后附录提供快速索引,即查、即学、...

    C#程序开发范例宝典(第2版).part08

    精选570个典型范例,全面覆盖实用和热点技术,涉及面广,实用性强源于实际项目开发,帮助读者短时间掌握更多实用技术,提高编程水平范例经过精心编排,重点、难点突出,易学易懂书后附录提供快速索引,即查、即学、...

    C#程序开发范例宝典(第2版).part02

    精选570个典型范例,全面覆盖实用和热点技术,涉及面广,实用性强源于实际项目开发,帮助读者短时间掌握更多实用技术,提高编程水平范例经过精心编排,重点、难点突出,易学易懂书后附录提供快速索引,即查、即学、...

    C#程序开发范例宝典(第2版).part12

    精选570个典型范例,全面覆盖实用和热点技术,涉及面广,实用性强源于实际项目开发,帮助读者短时间掌握更多实用技术,提高编程水平范例经过精心编排,重点、难点突出,易学易懂书后附录提供快速索引,即查、即学、...

Global site tag (gtag.js) - Google Analytics