MySQL get a random value between two values

前端 未结 5 1232
日久生厌
日久生厌 2020-12-03 01:01

I have two columns in a row: min_value, max_value. Is there a way to do a select like:

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


        
相关标签:
5条回答
  • 2020-12-03 01:22

    Actually, ROUND((RAND() * (max-min))+min) is the best way in MySQL to do what you'd like. It is also the best way in ActionScript, JavaScript, and Python. Honestly, I prefer it to the PHP way because it is more convenient.

    Because I don't know how many rows you'll be returning, I can't advise you whether it is better to use PHP or MySQL for this, but if you're dealing with a large number of values you probably are better off using MySQL.

    Addendum


    So, there was a question as to whether this is better in PHP or MySQL. Instead of getting into a debate on principles, I ran the following:

    <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 is faster by about 2-3%.

    If you use this, however (note, more columns return by 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 comes out behind by 3-4% (very inconsistent results) (about the same results if you don't use an array index assignment for $r[2]).

    The major difference, it seems, comes from the number of records return to PHP and not the randomization system itself. So, if you need column A, column B, and a random value, use PHP. If you only need the random value, then use MySQL.

    0 讨论(0)
  • 2020-12-03 01:22

    This method guarantees the same statistical probability for each value:

    SELECT FLOOR((RAND() * (max-min+1))+min)
    
    0 讨论(0)
  • 2020-12-03 01:26

    Could you do something like this?

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

    See this post

    0 讨论(0)
  • 2020-12-03 01:29

    in case minimum range is 1, you can simply

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


    in case minimum range is 0, you can even more simply

    SELECT FLOOR((RAND() * max_range))
    
    0 讨论(0)
  • 2020-12-03 01:29

    Depending on how many rows you have in the table(s), using rand() in a query or subquery can be extremely slow.

    You can seriously improve the speed by first putting the random value in a variable and then just using that in your query.

    For example on a table with over 4 million rows...

    This took over 10 minutes:

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

    While this took about 3 seconds on average:

    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;
    

    You might even be able to put this into a stored procedure then if it's something you would want to do or re-use often. The stored procedure could then be called from PHP or Python or wherever

    0 讨论(0)
提交回复
热议问题