- NetBeans插件编程大赛
轻松编程,提交作品就有奖! 获奖作者将被邀请参加2007中国JaVa大会 - 中科院5大IT领域工硕报名
招生人数高达230人, 进校不离岗,在职学习 - Solaris 10一个很棒的特性
Solaris 10目前既可支持SPARC处理器, Solaris 10上有600多个新特性,之前和大 - 评论专栏:JavaServer 新手入门
尽管本文针对初学者 准确说明却对各个层次的读者都会有所帮助 - 多核编程的几个难题及其应对策略(难题一)
非常有用的实用资料
最近在论坛看到有人问,如何快速生成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
RAND ()
FROM sysobjects
3. 在效率控制,使用循环+批量生成的方式,而不是传统的逐个生成。在SQL Server中,每个插入语句都会有一个内部的事务处理,如果逐条插入,则事务的开销太大,效率势必非常低;不考虑一次性生成100万数据,一则因为生成的数据可能有重复的,去掉重复就没有100万了,二则一次性生成100万数据,消耗的内存和CPU资源也很高,一般的电脑可能承受不住
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1099215
如何快速生成100万不重复的8位编号
如何快速生成100万不重复的8位编号
不是我要钻牛角尖,这个要求,数字0-1000000也满足要求啊,呵呵,如果不特别说明的话。
请问楼主,示例执行了多长时间?
假设我要产生从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和我联系。
假设我要在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和我联系。
假设我要在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次就可完成。
至于代码,很简单,自己写吧,这里只给出思路!!
问题是O提的.
谢谢邹老大,确实厉害.
我现在要生成18位随机数。
用你这个程序跑了后,发现很多不够18位的数。
我可以怎么样在这里加个较验,同时又能高效的写入表里
[原创] 生成X个不重复的Y位长度的随机数
http://blog.csdn.net/cuixiping/archive/2007/04/13/1563708.aspx
邹大哥去指点指点吧。
我用邹建大哥的上面代码在查询分析器里面会报语法错误啊!
我的sqlserver 2000.
/*
[原创] 生成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;