SQL Server随机使用种子

时间:2014-09-16 15:07:30

标签: sql sql-server random random-seed

我想使用种子使用随机数向我的表中添加一列。 如果我使用兰德:

select *, RAND(5) as random_id from myTable

对于random_id列中的所有行,我得到一个相等的值(例如0.943597390424144)。我希望这个值对于每一行都是不同的 - 并且每次我将它传递给0.5值(例如),它将再次是相同的值(因为种子应该工作......)。

我该怎么做?

( 例如,在PostrgreSql中我可以写

SELECT setseed(0.5); SELECT t.* , random() as random_id FROM myTable t

我将在每一行中获得不同的值。 )


修改

在我看到这里的评论后,我设法以某种方式解决了这个问题 - 但它根本没有效率。 如果有人知道如何改进它 - 它会很棒。如果没有 - 我将不得不寻找另一种方式。

我在here中使用了该示例的基本概念。

使用空白种子值创建临时表

select * into t_myTable  from (
select t.*, -1.00000000000000000 as seed
       from myTable t
       ) as temp

为每个种子值添加一个随机数,一次一行(这是不好的部分......):

USE CPatterns;
GO
DECLARE @seed float;
DECLARE @id int;
DECLARE VIEW_CURSOR CURSOR FOR
select id
from t_myTable t;
OPEN VIEW_CURSOR;
FETCH NEXT FROM VIEW_CURSOR
into @id;
set @seed = RAND(5);

WHILE @@FETCH_STATUS = 0
   BEGIN
      set @seed = RAND();
         update t_myTable set seed = @seed where id = @id

      FETCH NEXT FROM VIEW_CURSOR
         into @id;

   END;
CLOSE VIEW_CURSOR;
DEALLOCATE VIEW_CURSOR;
GO

使用种子值创建视图并按其排序

create view my_view AS 
select row_number() OVER (ORDER BY seed, id) AS  source_id ,t.*
       from t_myTable t

4 个答案:

答案 0 :(得分:1)

我认为在表格中获取可重复随机ID的最简单方法是在每一行使用row_number()或固定id。我假设您有一个名为id的列,每行都有不同的值。

这个想法只是将其用作种子:

select rand(id*1), as random_id
from mytable;

请注意,id的种子是整数,而不是浮点数。如果你想要一个浮点种子,你可以用checksum()做一些事情:

select rand(checksum(id*0.5)) as random_id
. . .

如果你这样做是为了取样(例如你会说10 {1}的random_id < 0.1,那么我经常在row_number()上使用模运算:

with t as (
      select t.* row_number() over (order by id) as seqnum
      from mytable t
     )
select *
from t
where ((seqnum * 17 + 71) % 101) < 0.1

这会返回大约10%的数字(好吧,真的是10/101)。你可以通过摆弄常数来调整样本。

答案 1 :(得分:1)

有人使用newid()进行了类似的查询,但我为您提供了适用于我的解决方案。

有一种解决方法涉及到newid()而不是rand,但是它给您相同的结果。您可以单独执行它,也可以在列中将其执行。这将导致每行随机值,而不是select语句中每行相同的值。 如果您需要一个0到N之间的随机数,只需将100更改为所需的数字即可。

SELECT TOP 10 [Flag forca]
,1+ABS(CHECKSUM(NEWID())) % 100 AS RANDOM_NEWID
,RAND() AS  RANDOM_RAND
FROM PAGSEGURO_WORK.dbo.jobSTM248_tmp_leitores_iso

Result

答案 2 :(得分:0)

所以,如果有一天会有人,这就是我最终做的事情。

我在服务器端生成随机种子值(在我的例子中是Java),然后创建一个包含两列的表:id和生成的random_id。 现在,我在表格和原始数据之间创建了inner join视图。

生成的SQL看起来像这样:

CREATE TABLE SEED_DATA(source_id INT PRIMARY KEY, random_id float NOT NULL);
select Rand(5); 
insert into SEED_DATA values(1,Rand());
insert into SEED_DATA values(2, Rand());
insert into SEED_DATA values(3, Rand());
.
.
.
insert into SEED_DATA values(1000000, Rand());

CREATE VIEW DATA_VIEW
as  
    SELECT row_number() OVER (ORDER BY random_id, id) AS source_id,column1,column2,...
    FROM 
        ( select * from SEED_DATA tmp 
          inner join my_table i on tmp.source_id = i.id) TEMP 

另外,我分批创建随机数,每批10,000个左右(可能更高),因此在服务器端不会造成太大影响,对于每个批次,我将其单独插入表中执行。

所有这些因为我找不到一个好的方法来完成我想要的纯粹在SQL中。一行一行更新真的效率不高。

我从这个故事得出的结论是,SQL Server有时真的很烦人......

答案 3 :(得分:0)

您可以从种子转换随机数:

rand(row_number over (order by ___, ___,___))

然后将其转换为varchar ,然后使用最后3个字符作为另一个种子。 这会给你一个很好的随机值:

rand(right(cast(rand(row_number() over(x,y,x)) as varchar(15)), 3)