繁体   English   中英

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

[英]MySQL get a random value between two values

我连续有两列: min_valuemax_value 有没有办法像 select 一样:

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

我确实意识到RAND做了不同的事情。 我想出的最接近的(在帮助下)是(RAND() * (max-min))+min ,尽管它会产生一个浮点数,然后我需要它来 ROUND() ,这是完全错误的。

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

实际上, 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。

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

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

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

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


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

SELECT FLOOR((RAND() * max_range))

你能做这样的事情吗?

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

看到这个帖子

根据表中有多少行,在查询或子查询中使用 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 或任何地方调用存储过程

您可以按 rand 使用 order

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM