如何为 T-SQL 选择中的每一行生成随机数?
我的表中的每一行都需要一个不同的随机数。 以下看似显而易见的代码对每一行使用相同的随机值。
SELECT table_name, RAND() magic_number
FROM information_schema.tables
我想从中得到一个 INT 或一个 FLOAT。 故事的其余部分是我将使用这个随机数来创建相对于已知日期的随机日期偏移量,例如相对于开始日期的 1-14 天偏移量。
这是针对 Microsoft SQL Server 2000 的。
I need a different random number for each row in my table. The following seemingly obvious code uses the same random value for each row.
SELECT table_name, RAND() magic_number
FROM information_schema.tables
I'd like to get an INT or a FLOAT out of this. The rest of the story is I'm going to use this random number to create a random date offset from a known date, e.g. 1-14 days offset from a start date.
This is for Microsoft SQL Server 2000.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(21)
每行中是否有一个整数值可以作为种子传递给 RAND 函数?
要获得 1 到 14 之间的整数,我相信这会起作用:
Do you have an integer value in each row that you could pass as a seed to the RAND function?
To get an integer between 1 and 14 I believe this would work:
这里的随机数将在 20 到 30 之间。
round
最多给出两位小数。如果你想要负数,你可以这样做
然后最小值将是-60,最大值将是-50。
Here the random number will come in between 20 and 30.
round
will give two decimal place maximum.If you want negative numbers you can do it with
Then the min value will be -60 and max will be -50.
如果您需要保留种子以便每次生成“相同”的随机数据,您可以执行以下操作:
1。 创建一个返回 select rand() 的视图
2。 创建一个从视图中选择值的 UDF。
3. 在选择数据之前,为 rand() 函数提供种子,然后在 select 语句中使用 UDF。
If you need to preserve your seed so that it generates the "same" random data every time, you can do the following:
1. Create a view that returns select rand()
2. Create a UDF that selects the value from the view.
3. Before selecting your data, seed the rand() function, and then use the UDF in your select statement.
尝试在 RAND(seedInt) 中使用种子值。 RAND() 每个语句只会执行一次,这就是为什么您每次都会看到相同的数字。
try using a seed value in the RAND(seedInt). RAND() will only execute once per statement that is why you see the same number each time.
如果您不需要它是一个整数,而是任何随机的唯一标识符,您可以使用
newid()
If you don't need it to be an integer, but any random unique identifier, you can use
newid()
您需要为每一行调用 RAND()。 这是一个很好的例子
https://web.archive.org/web/20090216200320/http://dotnet.org.za/calmyourself/archive/2007/04/13 /sql-rand-trap-same-value-per-row.aspx
You would need to call RAND() for each row. Here is a good example
https://web.archive.org/web/20090216200320/http://dotnet.org.za/calmyourself/archive/2007/04/13/sql-rand-trap-same-value-per-row.aspx
我有时对所选“答案”遇到的问题是分布并不总是均匀的。 如果您需要在很多行中非常均匀地分布随机 1 - 14,您可以执行类似的操作(我的数据库有 511 个表,因此这有效。如果您的行数少于随机数范围,则这不起作用好):
这种方法与正常随机解决方案相反,因为它保持数字排序并随机化另一列。
请记住,我的数据库中有 511 个表(仅与我们从 information_schema 中选择的内容相关)。 如果我将前面的查询放入临时表 #X 中,然后对结果数据运行此查询:
我得到此结果,显示我的随机数非常均匀地分布在许多行中:
The problem I sometimes have with the selected "Answer" is that the distribution isn't always even. If you need a very even distribution of random 1 - 14 among lots of rows, you can do something like this (my database has 511 tables, so this works. If you have less rows than you do random number span, this does not work well):
This kind of does the opposite of normal random solutions in the sense that it keeps the numbers sequenced and randomizes the other column.
Remember, I have 511 tables in my database (which is pertinent only b/c we're selecting from the information_schema). If I take the previous query and put it into a temp table #X, and then run this query on the resulting data:
I get this result, showing me that my random number is VERY evenly distributed among the many rows:
这很简单:
这会将 0-99 之间的随机数放入表中:
It's as easy as:
And this will put a random number between 0-99 into a table:
一直对我有用
has always worked for me
使用 newid()
或可能这
Use newid()
or possibly this
如果你想生成一个 1 到 14 之间的随机数。
或者
If you want to generate a random number between 1 and 14 inclusive.
OR
1 到 10 之间的数字。
Number between 1 and 10.
试试这个:
其中
a
是较小的数字,b
是较大的数字Try this:
Where
a
is the lower number andb
is the upper number如果您需要特定数量的随机数,可以使用递归 CTE:
If you need a specific number of random number you can use recursive CTE:
看看 SQL Server - 基于随机数的设置,其中有非常详细的解释。
总而言之,以下代码生成一个 0 到 13 之间(含)的均匀分布随机数:
要更改范围,只需更改表达式末尾的数字即可。 如果您需要一个包含正数和负数的范围,请格外小心。 如果你做错了,可能会重复计算数字 0。
对房间里的数学迷的一个小警告:这段代码中有一个非常轻微的偏差。
CHECKSUM()
产生的数字在 sql Int 数据类型的整个范围内是统一的,或者至少与我(编辑器)测试所显示的接近。 但是,当 CHECKSUM() 生成位于该范围最顶端的数字时,将会出现一些偏差。 每当您获得最大可能整数和最大整数之前所需范围大小的最后一个精确倍数(在本例中为 14)之间的数字时,这些结果都会优先于无法生成的范围的剩余部分最后一个是 14 的倍数。举个例子,假设 Int 类型的整个范围只有 19。19 是您可以容纳的最大整数。 当 CHECKSUM() 结果为 14-19 时,这些对应于结果 0-5。 这些数字比 6-13 更受青睐,因为 CHECKSUM() 生成它们的可能性是 6-13 的两倍。 从视觉上证明这一点更容易。 下面是我们的假想整数范围的整个可能结果集:
您可以在这里看到,产生某些数字的机会比其他数字更多:偏差。 值得庆幸的是,Int 类型的实际范围要大得多……以至于在大多数情况下偏差几乎无法检测到。 但是,如果您发现自己为严格的安全代码这样做,则需要注意这一点。
Take a look at SQL Server - Set based random numbers which has a very detailed explanation.
To summarize, the following code generates a random number between 0 and 13 inclusive with a uniform distribution:
To change your range, just change the number at the end of the expression. Be extra careful if you need a range that includes both positive and negative numbers. If you do it wrong, it's possible to double-count the number 0.
A small warning for the math nuts in the room: there is a very slight bias in this code.
CHECKSUM()
results in numbers that are uniform across the entire range of the sql Int datatype, or at least as near so as my (the editor) testing can show. However, there will be some bias when CHECKSUM() produces a number at the very top end of that range. Any time you get a number between the maximum possible integer and the last exact multiple of the size of your desired range (14 in this case) before that maximum integer, those results are favored over the remaining portion of your range that cannot be produced from that last multiple of 14.As an example, imagine the entire range of the Int type is only 19. 19 is the largest possible integer you can hold. When CHECKSUM() results in 14-19, these correspond to results 0-5. Those numbers would be heavily favored over 6-13, because CHECKSUM() is twice as likely to generate them. It's easier to demonstrate this visually. Below is the entire possible set of results for our imaginary integer range:
You can see here that there are more chances to produce some numbers than others: bias. Thankfully, the actual range of the Int type is much larger... so much so that in most cases the bias is nearly undetectable. However, it is something to be aware of if you ever find yourself doing this for serious security code.
当在一个批次中多次调用时,rand() 返回相同的数字。
我建议使用 Convert(
varbinary
,newid()
) 作为种子参数:newid()
保证每次返回不同的值调用它的时间,即使是在同一个批次中,因此使用它作为种子将提示 rand() 每次给出不同的值。编辑以获得 1 到 14 之间的随机整数。
When called multiple times in a single batch, rand() returns the same number.
I'd suggest using convert(
varbinary
,newid()
) as the seed argument:newid()
is guaranteed to return a different value each time it's called, even within the same batch, so using it as a seed will prompt rand() to give a different value each time.Edited to get a random whole number from 1 to 14.
上面将生成一个介于 0 和 1 之间(不包括 0 和 1)的(伪)随机数。 如果在选择中使用,由于每行的种子值都会发生变化,因此它将为每行生成一个新的随机数(但是不能保证每行生成唯一的数字)。
与上限 10 组合时的示例(生成数字 1 - 10):
Transact-SQL 文档:
CAST()
:https://learn.microsoft.com/en-us/sql/t-sql/functions/cast- and-convert-transact-sqlRAND()
: http://msdn.microsoft.com/en-us/library/ms177610.aspxCHECKSUM()
: http://msdn.microsoft.com/en-us/library/ms189788.aspxNEWID()
: https://learn.microsoft.com /en-us/sql/t-sql/functions/newid-transact-sqlThe above will generate a (pseudo-) random number between 0 and 1, exclusive. If used in a select, because the seed value changes for each row, it will generate a new random number for each row (it is not guaranteed to generate a unique number per row however).
Example when combined with an upper limit of 10 (produces numbers 1 - 10):
Transact-SQL Documentation:
CAST()
: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sqlRAND()
: http://msdn.microsoft.com/en-us/library/ms177610.aspxCHECKSUM()
: http://msdn.microsoft.com/en-us/library/ms189788.aspxNEWID()
: https://learn.microsoft.com/en-us/sql/t-sql/functions/newid-transact-sql生成 1000 到 9999 之间的随机数(包括 1000 和 9999):
“+1” - 包括上限值(前面的示例为 9999)
Random number generation between 1000 and 9999 inclusive:
"+1" - to include upper bound values(9999 for previous example)
回答老问题,但以前没有提供过这个答案,希望这对于通过搜索引擎找到此结果的人有用。
SQL Server 2008 中引入了一个新函数
CRYPT_GEN_RANDOM(8)
,它使用 CryptoAPI 生成加密的强随机数,返回为VARBINARY(8000)
。 这是文档页面:https: //learn.microsoft.com/en-us/sql/t-sql/functions/crypt-gen-random-transact-sql因此,要获取随机数,您只需调用该函数并将其转换为必要的类型:
或者要获得 -1 和 +1 之间的
float
,您可以执行以下操作:Answering the old question, but this answer has not been provided previously, and hopefully this will be useful for someone finding this results through a search engine.
With SQL Server 2008, a new function has been introduced,
CRYPT_GEN_RANDOM(8)
, which uses CryptoAPI to produce a cryptographically strong random number, returned asVARBINARY(8000)
. Here's the documentation page: https://learn.microsoft.com/en-us/sql/t-sql/functions/crypt-gen-random-transact-sqlSo to get a random number, you can simply call the function and cast it to the necessary type:
or to get a
float
between -1 and +1, you could do something like this:如果在表 SELECT 查询中使用,Rand() 函数将生成相同的随机数。 如果您对 Rand 函数使用种子,则同样适用。 另一种方法是使用以下方法:
从 获取信息这里很好地解释了这个问题。
The Rand() function will generate the same random number, if used in a table SELECT query. Same applies if you use a seed to the Rand function. An alternative way to do it, is using this:
Got the information from here, which explains the problem very well.