1

I want to generate non-repeated random numbers from a set of array elements. My array elements are from database. Like this

$b1 = "SELECT id FROM datacards WHERE id<>".$dcard."";
$b2 = mysqli_query($con, $b1) or die (mysqli_query($con));
while($b3 = mysqli_fetch_array($b2))
{

$ids[] = $b3['id']; 
}
$Myarray=implode("," , $ids);   

I have to generate 2 non repeated random numbers from Myarray. Myarray contains (ids) integer numbers from 1 to 60 except 1 number which is

$b1 = "SELECT id FROM datacards WHERE id<>".$dcard."";

How can i do it?

3
  • WHERE NOT IN ($alreadyFetchedNums) ORDER BY RAND() Commented Apr 24, 2018 at 6:54
  • Is $dcard user-supplied data? (from GET / POST) Commented Apr 24, 2018 at 7:33
  • Yes it Is user supplied data Commented Apr 24, 2018 at 7:37

2 Answers 2

1
$b1 = 'SELECT `id` FROM `datacards` WHERE `id` <> ' . (int)$dcard . ' ORDER BY RAND() LIMIT 2';

This should exclude the one id and select 2 random ids.

Or with an oop prepared statement (assuming $_GET['dcard']):

if (!empty($_GET['dcard']) && ctype_digit($_GET['dcard'])) {
    $db = new mysqli('localhost', 'username', 'password', 'database');
    if ($stmt = $db->prepare('SELECT `id` FROM `datacards` WHERE `id` <> ? ORDER BY RAND() LIMIT 2')  &&
        $stmt->bind_param('i', $_GET['dcard']) &&
        $stmt->execute() &&
        $stmt->bind_result($id)
    ) {
        while($stmt->fetch()){
            $ids[] = $id;
        }
        $stmt->close();
    }
} else {
    echo 'Missing/Invalid input data.';
}

Or you could use GROUP_CONCAT() in your query and retrieve a single object.

Sign up to request clarification or add additional context in comments.

2 Comments

To increase PHP speed, use simple quotes in combination with . to concate. Because double quotes is for in chain vars. like ...`id` <> '$dcard' ORDER...
That's fine. No user will ever notice the speed increase. If you were going to say this on all similar cases on StackOverflow, you would be leaving tens of thousands of comments.
1

Untested, but hopefully it will get you using prepared statements, and uses ORDER BY RAND() that was suggested by Royal Bg:

$query = 'SELECT id FROM datacards WHERE id <> ? ORDER BY RAND() LIMIT 2';
$stmt = mysqli_prepare($con,$query) or die( mysqli_error($con) );
mysqli_stmt_bind_param($stmt, 's', $dcard);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
while($row = mysqli_fetch_array($result))
{
    $ids[] = $row['id']; 
}
$Myarray = implode("," , $ids);

Note that ORDER BY RAND() is very slow with large data due to having to reorder all the rows matched. It's better to first count the rows in the table, then generate a number between 0 and the number of rows minus one. This number will represent the index of the record in the database. Then generate another random number between 0 and the number of rows minus two. This will represent another record index in the database. If the second index is equal to or greater than the first index, then add one to its value. With this algorithm, you'll have two completely random non-repeating indexes from the database. Then you'd ORDER BY field(id, ?, ?) LIMIT 2 with the two question marks being the ids you want to select, and the order you want to select them. You can find the FIELD function of MySQL in the manual here:
https://dev.mysql.com/doc/refman/5.5/en/string-functions.html#function_field

3 Comments

I didn't know when posting if prepared statements were necessary, but I appreciate and share your concern. I am using (int) to hedge my bets. The table is not huge so there is little impact from using RAND().
You will need i in your bind instead of s.
@mickmackusa MySQL works with integers treated like strings just fine. The situations where i becomes mandatory are pretty slim. But yeah, the OP did mention he is using integers so i would make sense here. Would it have any differences in this context? Nah. In fact I can't remember the last time i ever had to bind with i.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.