MySQL获得两个值之间的随机值

时间:2011-07-01 15:44:08

标签: php mysql

我连续有两列:min_valuemax_value。有没有办法做一个选择:

SELECT RAND(`min_v`, `max_v`) `foo` [..]

我确实认识到RAND做了不同的事情;我得到的最近的(有帮助)是(RAND() * (max-min))+min,虽然它会产生一个浮点数,然后我需要ROUND(),这完全错了。

除非有人能提出替代方案(这将非常有用),否则我将采用PHP方式。

6 个答案:

答案 0 :(得分:52)

实际上,ROUND((RAND() * (max-min))+min)是MySQL做你想做的最好的方式。它也是ActionScript,JavaScript和Python的最佳方式。老实说,我更喜欢PHP方式,因为它更方便。

因为我不知道你将返回多少行,所以我不能告诉你使用PHP或MySQL是否更好,但如果你处理大量的值,你可能最好使用MySQL。

附录


所以,有一个问题是这在PHP或MySQL中是否更好。我没有参与关于原则的辩论,而是运行了以下内容:

<pre><?php

$c = mysql_connect('localhost', 'root', '');

if(!$c) die('!');
echo mysql_select_db('test', $c)?'Connection':'Failure';
echo PHP_EOL;

echo ':::::::::::::::::::::::::BEGINNING MYSQL RAND::::::::::::::::::::::::::::::'.PHP_EOL;
$start = microtime(1);
for( $i = 0; $i < 100000; $i++ )
{
    $r = mysql_query( 'SELECT ROUND(RAND() * (200-10) + 10) FROM dual' );
    $r = mysql_fetch_array( $r );
}
$end = microtime(1);

echo  ($end - $start) . " for MySQL select".PHP_EOL;

echo ':::::::::::::::::::::::::BEGINNING PHP RAND::::::::::::::::::::::::::::::' .PHP_EOL;
$start = microtime(1);
for( $i = 0; $i < 100000; $i++ )
{
    $r = mysql_query( 'SELECT 200 AS two, 10 AS tem FROM dual' );
    $r = mysql_fetch_array( $r );
    $r[2]= rand($r[0], $r[1]);
}
$end = microtime(1);

echo  ($end - $start) . " for PHP select".PHP_EOL;

MySQL的速度提高了2-3%。

但是如果你使用它(请注意,MySQL会返回更多列):

<pre><?php

$c = mysql_connect('localhost', 'root', '');

if(!$c) die('!');
echo mysql_select_db('test', $c)?'Connection':'Failure';
echo PHP_EOL;

echo ':::::::::::::::::::::::::BEGINNING MYSQL RAND::::::::::::::::::::::::::::::'.PHP_EOL;
$start = microtime(1);
for( $i = 0; $i < 100000; $i++ )
{
    $r = mysql_query( 'SELECT ROUND(RAND() * (200-10) + 10) as rd, 200 as two, 10 as ten FROM dual' );
    $r = mysql_fetch_array( $r );
}
$end = microtime(1);

echo  ($end - $start) . " for MySQL select".PHP_EOL;

echo ':::::::::::::::::::::::::BEGINNING PHP RAND::::::::::::::::::::::::::::::' .PHP_EOL;
$start = microtime(1);
for( $i = 0; $i < 100000; $i++ )
{
    $r = mysql_query( 'SELECT 200 AS two, 10 AS tem FROM dual' );
    $r = mysql_fetch_array( $r );
    $r[2]= rand($r[0], $r[1]);
}
$end = microtime(1);

echo  ($end - $start) . " for PHP select".PHP_EOL;

MySQL落后3-4%(非常不一致的结果)(如果不为$ r [2]使用数组索引赋值,结果大致相同)。

似乎主要区别在于返回PHP的记录数量,而不是随机化系统本身。因此,如果您需要列A,列B和随机值,请使用PHP。如果您只需要随机值,那么使用MySQL。

答案 1 :(得分:34)

此方法保证每个值具有相同的统计概率:

SELECT FLOOR((RAND() * (max-min+1))+min)

答案 2 :(得分:2)

你可以这样做吗?

SELECT id, (FLOOR( 1 + RAND( ) *60 )) AS timer
FROM users
LIMIT 0 , 30

请参阅this post

答案 3 :(得分:1)

如果最小范围是1,您可以简单地

SELECT FLOOR((RAND() * max_range) + 1)


如果最小范围是0,你甚至可以更简单地

SELECT FLOOR((RAND() * max_range))

答案 4 :(得分:0)

根据表中有多少行,在查询或子查询中使用rand()可能会非常慢。

您可以通过先将随机值放入变量,然后在查询中使用它来严重提高速度。

例如,在具有超过400万行的表上...

这花费了超过10分钟的时间:

SELECT
    *
FROM
    `customers` `Customer`
WHERE
    `id` = (
        SELECT
            FLOOR((RAND() * (max(`CustomerRand`.`id`) - min(`CustomerRand`.`id`) + 1)) + min(`CustomerRand`.`id`)) `random_id`
        FROM
            `customers` `CustomerRand`
    );

这平均需要3秒钟:

SELECT
   FLOOR((RAND() * (max(`CustomerRand`.`id`) - min(`CustomerRand`.`id`) + 1)) + min(`CustomerRand`.`id`)) `random_id`
FROM `customers` `CustomerRand` INTO @rand_id;

SELECT * FROM `customers` WHERE `id` = @rand_id;

您甚至可以将其放入存储过程中,如果您想这样做或经常重复使用它。然后可以从PHP或Python或任何地方调用存储过程

答案 5 :(得分:0)

您可以使用 rand 命令

SELECT virtual.num
FROM (
         SELECT 1 AS num UNION
         SELECT 2 AS num UNION
         SELECT 3 AS num
     ) virtual
ORDER BY RAND()
LIMIT 1