UPDATE CattleProds
SET SheepTherapy=(ROUND((RAND()* 10000),0))
WHERE SheepTherapy IS NULL
Answers:
代替rand(),使用newid(),对结果中的每一行都重新计算。通常的方法是使用校验和的模。请注意,这checksum(newid())可能产生-2,147,483,648并导致上的整数溢出abs(),因此我们需要在对校验和返回值进行模运算之前将其转换为绝对值。
UPDATE CattleProds
SET    SheepTherapy = abs(checksum(NewId()) % 10000)
WHERE  SheepTherapy IS NULL
这将生成一个介于0和9999之间的随机数。
如果您使用的是SQL Server 2008,也可以使用
 CRYPT_GEN_RANDOM(2) % 10000
这似乎更简单(它也按行计算一次,newid如下所示)
DECLARE @foo TABLE (col1 FLOAT)
INSERT INTO @foo SELECT 1 UNION SELECT 2
UPDATE @foo
SET col1 =  CRYPT_GEN_RANDOM(2) % 10000
SELECT *  FROM @foo
返回值(2个随机的可能不同的数字)
col1
----------------------
9693
8573
考虑无法解释的下降投票,我能想到的唯一合理原因是,因为生成的随机数在0-65535之间,不能被10,000整除,所以有些数字会略有超出。一种解决方法是将其包装在标量UDF中,该标量UDF会丢弃超过60,000的任何数字,然后递归调用自身以获取替换数字。
CREATE FUNCTION dbo.RandomNumber()
RETURNS INT
AS
  BEGIN
      DECLARE @Result INT
      SET @Result = CRYPT_GEN_RANDOM(2)
      RETURN CASE
               WHEN @Result < 60000
                     OR @@NESTLEVEL = 32 THEN @Result % 10000
               ELSE dbo.RandomNumber()
             END
  END  
虽然我确实喜欢使用CHECKSUM,但我觉得使用它是一种更好的方法NEWID(),因为您不必经过复杂的数学运算即可生成简单的数字。
ROUND( 1000 *RAND(convert(varbinary, newid())), 0)
您可以将1000您要设置为限制的数字替换为,并且始终可以使用加号来创建范围,例如,您想要在100和之间的随机数200,可以执行以下操作:
100 + ROUND( 100 *RAND(convert(varbinary, newid())), 0)
将其放到您的查询中:
UPDATE CattleProds 
SET SheepTherapy= ROUND( 1000 *RAND(convert(varbinary, newid())), 0)
WHERE SheepTherapy IS NULL
我针对RAND()测试了2种基于集合的随机方法,每个方法都产生了100,000,000行。为了平整该字段,输出是一个介于0-1之间的浮点,以模拟RAND()。大多数代码正在测试基础结构,因此我在这里总结算法:
-- Try #1 used
(CAST(CRYPT_GEN_RANDOM(8) AS BIGINT)%500000000000000000+500000000000000000.0)/1000000000000000000 AS Val
-- Try #2 used
RAND(Checksum(NewId()))
-- and to have a baseline to compare output with I used
RAND() -- this required executing 100000000 separate insert statements
显然,使用CRYPT_GEN_RANDOM是最随机的,因为从一组10 ^ 18的数字中抽出10 ^ 8的数字时,甚至只有.000000001%的机会看到甚至1个重复项。哎呀,我们不应该看到任何重复的,而且没有!在我的笔记本电脑上生成此设置花了44秒钟。
Cnt     Pct
-----   ----
 1      100.000000  --No duplicates
SQL Server执行时间:CPU时间= 134795毫秒,经过的时间= 39274毫秒。
IF OBJECT_ID('tempdb..#T0') IS NOT NULL DROP TABLE #T0;
GO
WITH L0   AS (SELECT c FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS D(c))  -- 2^4  
    ,L1   AS (SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B)    -- 2^8  
    ,L2   AS (SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B)    -- 2^16  
    ,L3   AS (SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B)    -- 2^32  
SELECT TOP 100000000 (CAST(CRYPT_GEN_RANDOM(8) AS BIGINT)%500000000000000000+500000000000000000.0)/1000000000000000000 AS Val
  INTO #T0
  FROM L3;
 WITH x AS (
     SELECT Val,COUNT(*) Cnt
      FROM #T0
     GROUP BY Val
)
SELECT x.Cnt,COUNT(*)/(SELECT COUNT(*)/100 FROM #T0) Pct
  FROM X
 GROUP BY x.Cnt;
这种方法的随机性降低了近15个数量级,其速度并不快两倍,仅需23秒即可生成1亿个数字。
Cnt  Pct
---- ----
1    95.450254    -- only 95% unique is absolutely horrible
2    02.222167    -- If this line were the only problem I'd say DON'T USE THIS!
3    00.034582
4    00.000409    -- 409 numbers appeared 4 times
5    00.000006    -- 6 numbers actually appeared 5 times 
SQL Server执行时间:CPU时间= 77156 ms,经过的时间= 24613 ms。
IF OBJECT_ID('tempdb..#T1') IS NOT NULL DROP TABLE #T1;
GO
WITH L0   AS (SELECT c FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS D(c))  -- 2^4  
    ,L1   AS (SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B)    -- 2^8  
    ,L2   AS (SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B)    -- 2^16  
    ,L3   AS (SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B)    -- 2^32  
SELECT TOP 100000000 RAND(Checksum(NewId())) AS Val
  INTO #T1
  FROM L3;
WITH x AS (
    SELECT Val,COUNT(*) Cnt
     FROM #T1
    GROUP BY Val
)
SELECT x.Cnt,COUNT(*)*1.0/(SELECT COUNT(*)/100 FROM #T1) Pct
  FROM X
 GROUP BY x.Cnt;
RAND()本身对于基于集合的生成毫无用处,因此生成用于比较随机性的基准要花费6个小时以上的时间,必须重新启动几次才能最终获得正确数量的输出行。看起来随机性还有很多需要改进的地方,尽管它比使用checksum(newid())重新设定每行的种子更好。
Cnt  Pct
---- ----
1    99.768020
2    00.115840
3    00.000100  -- at least there were comparitively few values returned 3 times
由于重新启动,无法捕获执行时间。
IF OBJECT_ID('tempdb..#T2') IS NOT NULL DROP TABLE #T2;
GO
CREATE TABLE #T2 (Val FLOAT);
GO
SET NOCOUNT ON;
GO
INSERT INTO #T2(Val) VALUES(RAND());
GO 100000000
WITH x AS (
    SELECT Val,COUNT(*) Cnt
     FROM #T2
    GROUP BY Val
)
SELECT x.Cnt,COUNT(*)*1.0/(SELECT COUNT(*)/100 FROM #T2) Pct
  FROM X
 GROUP BY x.Cnt;
require_once('db/connect.php');
//rand(1000000 , 9999999);
$products_query = "SELECT id FROM products";
$products_result = mysqli_query($conn, $products_query);
$products_row = mysqli_fetch_array($products_result);
$ids_array = [];
do
{
    array_push($ids_array, $products_row['id']);
}
while($products_row = mysqli_fetch_array($products_result));
/*
echo '<pre>';
print_r($ids_array);
echo '</pre>';
*/
$row_counter = count($ids_array);
for ($i=0; $i < $row_counter; $i++)
{ 
    $current_row = $ids_array[$i];
    $rand = rand(1000000 , 9999999);
    mysqli_query($conn , "UPDATE products SET code='$rand' WHERE id='$current_row'");
}