开发者

MySQL: applying a random sort on multiple columns

开发者 https://www.devze.com 2023-01-04 02:46 出处:网络
In order to have a well scrambled table (for a psychological experiment), I\'d like to sort each column of my array by RAND().

In order to have a well scrambled table (for a psychological experiment), I'd like to sort each column of my array by RAND(). Althrough this code works:

SELECT Sort.Variable1, Sort.Variable2 FROM Sort ORDER BY Variable1, Variable2 ASC LIMIT 0 , 30

replacing "ASC" by "RAND()" make the query fail. Can someone give me an advice (even a solution with PHP) ?

Thanks

Edit:

Thanks to all your responses, I finally did it. Here's my PHP code for this (and sorry for the old-fashioned-not-brand-new-PDO-queries). Even if it's maybe useless, I post it:

           $i=0;
        //Describe to retrieve variables' names
        $sqlCol= 'DESCRIBE Sort';
        $sqlCol= mysql_query($sqlCol);
        while ($res=mysql_fetch_array($sqlCol)) {
            $var[$i]=$res['Field'];
            $i++;
        }
        $NbCol=mysql_num_rows($sqlCol); //Number of column to shuffle


        // Number of items for each column 
        $sqlCount= 'SELECT COUNT(*) FROM Sort';
        $req2= mysql_query($sqlCount) or die ('Err'开发者_如何学C);
        $NbLignes=  mysql_result($req2,0,0) or die ();//Number of rows


        //Data array
        $sql= "SELECT * FROM Sort";
        $req= mysql_query($sql) or die ('Err');
        $sort=mysql_fetch_array($req);
        for($i=0;$i<$NbCol;$i++) {
            ${'sql'.$i}='SELECT * FROM Sort ORDER BY RAND()';
            ${'input'.$i} = mysql_query(${'sql'.$i});
            while(${'array'.$i}=mysql_fetch_array(${'input'.$i})) {
                $bigArray[$i][]=${'array'.$i}[$i];
            }
        }

            for($i=0;$i<$NbLignes;$i++) {
                echo '<div id="q'.$i.'"style="margin-bottom: 50px; float:left">Question '.($i+1);
                echo '<ul id="sortable'.$i.'" class="sortable">';
                for($j=0;$j<$NbCol;$j++) {
                    echo '<li class="ui-state-default" id="'.$var[$j].$i.'" name="'.$var[$j].$i.'">'. $bigArray[$j][$i].'</li>';

                }
                echo '</ul></div>';
            }


Using ORDER BY RAND() won't randomize columns - it will randomize rows.

To randomize each column separately in SQL you can:

  • create a result set for each column separately
  • randomize the order of each of them
  • join the columns by row number

Unfortunately the MySQL development team haven't yet implemented ROW_NUMBER which would have made this task easy, but you can workaround it by simulating ROW_NUMBER using variables:

SELECT
    Column1,
    Column2
FROM
(
    SELECT Column1, @rn1 := @rn1 + 1 AS rank
    FROM Table1, (SELECT @rn1 := 0) vars
) T1
JOIN
(
    SELECT Column2, @rn2 := @rn2 + 1 AS rank
    FROM Table1, (SELECT @rn2 := 0) vars
    ORDER BY RAND()
) T2
ON T1.rank = T2.rank


Here is one possible method to do what you want using PHP. In the example code, I generate a list of numbers and place them in an array. You will need to grab the list from your database.

<?php

// Create 20 rows.
$rows = 20;

// Create an empty array to hold sorted values.
$sort = array();

// Fill the array with ascending/descending numbers.
for ($i = 0; $i < $rows; $i++) {
    $sort[$i]['var1'] = $i + 1;
    $sort[$i]['var2'] = $rows - $i; 
}

// Display the sorted array.
print "Sorted:\n";
print_rows($sort);

// Here's where the important bit happens:

// Create two arrays, each containing a list of the
// array keys from the sorted array (one for each column).
$var1 = array_keys($sort);
$var2 = array_keys($sort);

// Shuffle each list or array keys (one for each column).
shuffle($var1);
shuffle($var2);

// Create an empty array to hold shuffled values.
$shuffle = array();

// For every row in the list of shuffled keys, get
// the matching value from the sorted array, and
// place it in the shuffled array.
for ($i = 0; $i < $rows; $i++) {
    $shuffle[$i]['var1'] = $sort[$var1[$i]]['var1'];
    $shuffle[$i]['var2'] = $sort[$var2[$i]]['var2'];
}

// Display the shuffled array.
print "\nShuffled:\n";
print_rows($shuffle);


function print_rows($array) {
    print "Row | Var 1 | Var2\n";
    print "------------------\n";

    foreach ($array as $key=>$row) {
        printf("%3d | %5d | %4d\n", $key, $row['var1'], $row['var2']);
    }
}

?>

Here's the output:

Sorted:
Row | Var 1 | Var2
------------------
  0 |     1 |   20
  1 |     2 |   19
  2 |     3 |   18
  3 |     4 |   17
  4 |     5 |   16
  5 |     6 |   15
  6 |     7 |   14
  7 |     8 |   13
  8 |     9 |   12
  9 |    10 |   11
 10 |    11 |   10
 11 |    12 |    9
 12 |    13 |    8
 13 |    14 |    7
 14 |    15 |    6
 15 |    16 |    5
 16 |    17 |    4
 17 |    18 |    3
 18 |    19 |    2
 19 |    20 |    1

Shuffled:
Row | Var 1 | Var2
------------------
  0 |     8 |    2
  1 |    19 |   12
  2 |    14 |    5
  3 |    16 |   17
  4 |     2 |    8
  5 |    11 |    4
  6 |     7 |   11
  7 |     9 |   10
  8 |    12 |    1
  9 |     5 |    9
 10 |    13 |   20
 11 |    10 |    6
 12 |    17 |   19
 13 |    18 |   18
 14 |     4 |   14
 15 |    20 |    7
 16 |     3 |   16
 17 |    15 |   15
 18 |     6 |    3
 19 |     1 |   13

The code is a bit rough and ready. I'm sure there are a number of ways in which it could be improved. For example, you could change it so the it is able to handle a variable number of columns. However, the basic idea is there.

Edit:

Here's a tidied up version of the code, which will handle a variable number of columns:

// Here's where the important bit happens:

// Create an empty array to hold shuffled values.
$shuffle = array();

// Get the name of each column (key) in the array.
foreach (array_keys($sort[0]) as $col) {
    // Create an array of keys containing a list of the
    // array keys from the sorted array.
    $keys = array_keys($sort);

    // Shuffle each list or array keys.
    shuffle($keys);

    // For every row in the list of shuffled keys, get
    // the matching value from the sorted array, and
    // place it in the shuffled array.
    for ($i = 0; $i < $rows; $i++) {
        $shuffle[$i][$col] = $sort[$keys[$i]][$col];
    }
}

// Display the shuffled array.
print "\nShuffled:\n";
print_rows($shuffle);


You can do by 2 SQL statments:

 SELECT Sort.Variable1 FROM Sort ORDER BY RAND(), Variable1 LIMIT 0 , 30
 SELECT Sort.Variable2 FROM Sort ORDER BY RAND(), Variable2 LIMIT 0 , 30

if you need random in PHP array use: [array_rand][1]

<?php
// load all table values in array i just set them
$input = array("Neo", "Morpheus", "Trinity", "Cypher", "Tank"); 
$rand_keys = array_rand($input, 2);
echo $input[$rand_keys[0]] . "\n";
echo $input[$rand_keys[1]] . "\n";
?>
0

精彩评论

暂无评论...
验证码 换一张
取 消