Jump to content

Recommended Posts

Hi all,

 

So basically, I tried to generate random questions from database using mySQL and PHP.

I success in generating those questions, BUT the questions can sometimes appear again.

 

I have this PHP code of mine..


.......
	$sqlText="SELECT * FROM soal WHERE Difficulty='". $levelStr ."' AND Topic='". $topic ."'";
	$result=mysql_query($sqlText);

	$ctr=0;
	$arr=null;
	while($row = mysql_fetch_array($result))
	{
	   $arr[$ctr]=$row["SoalID"]."#".$row["Question"]."#".$row["Answer1"]."#".$row["Answer2"]."#".$row["Answer3"]."#".$row["Answer4"]."#".$row["CorrectAnswer"]."#".$row["Picture"];
	   $ctr++;
	}

    if ($ctr>0)
	{
		$totalRand=rand(10,50);
		for ($i=0;$i<$totalRand;$i++)
		{
		   $idx1=rand(0,$ctr-1);
		   $idx2=rand(0,$ctr-1);
		   
		   $res=$arr[$idx1];
		   $arr[$idx1]=$arr[$idx2];
		   $arr[$idx2]=$res;
		}
		$idx=rand(0,$ctr-1);
		echo $arr[$idx];
	}
  }

Any idea how to fix this problem?

Appreciate any help..

 

Thanks before

Try,
​$sqlText="SELECT * FROM soal WHERE Difficulty='". $levelStr ."' AND Topic='". $topic ." GROUP BY soal.Question ORDER BY soal.SoalID DESC'";

Its not working. The loaded data still repeatable. I'm thinking I should change this code rather than the sql, but I'm kinda confused what should I change here.

if ($ctr>0)
	{
		$totalRand=rand(10,50);
		for ($i=0;$i<$totalRand;$i++)
		{
		   $idx1=rand(0,$ctr-1);
		   $idx2=rand(0,$ctr-1);
		   
		   $res=$arr[$idx1];
		   $arr[$idx1]=$arr[$idx2];
		   $arr[$idx2]=$res;
		}
		$idx=rand(0,$ctr-1);
		echo $arr[$idx];
	}
Edited by puyunk

Before starting to build your app you have to better consider your database structure and normalize data.

 

You will find thousands of articles about that for sure.

 

I highly recommend you to start watching these 9

 

About my previous sql query, try to change it with this:

$sqlText = "
SELECT SoalID, Question, Answer1, Answer2, Answer3, Answer4, CorrectAnswer, Picture 
FROM (
     SELECT *, 
     @num := if(@Question = Question, @num + 1, 1) AS q_number,
     @Question := Question AS q_dummy
FROM soal
WHERE Difficulty='". $levelStr ."' AND Topic='". $topic ."') AS X
WHERE X.q_number = 1
";

Edited by jazzman1

since you are storing the retrieved rows in an array, just use shuffle() to randomize the rows in that array, then loop over the shuffled/random array to output the questions.

if ($ctr>0){
    shuffle($arr);
    foreach($arr as $question){
        echo $question;
    }
}

@jazzman, i don't know what you are reading in this thread, but the op has a number of questions for each difficulty/topic and wants to retrieve them and randomly output them. the problem is to output them without repeating any one question in a set.

 

 

@jazzman, i don't know what you are reading in this thread, but the op has a number of questions for each difficulty/topic and wants to retrieve them and randomly output them. the problem is to output them without repeating any one question in a set.

 

Yes, that's correct.

 

What's wrong about my reply?

your first query grouped by the question. unless there are duplicate questions at any difficulty/topic, there's nothing to group.

 

you second query is just numbering the questions in the query. the OP wants to randomize the display of the questions, so any numbering of the rows in the query would be out of order when displayed and has nothing to do with the stated problem.

your first query grouped by the question. unless there are duplicate questions at any difficulty/topic, there's nothing to group.

 

you second query is just numbering the questions in the query. the OP wants to randomize the display of the questions, so any numbering of the rows in the query would be out of order when displayed and has nothing to do with the stated problem.

 

Hm.....you are right, she will get the same result as GROUP BY Question, in case into one topic she has multiple different questions:

 

So, that should work,

$sqlText = "
SELECT SoalID, Question, Answer1, Answer2, Answer3, Answer4, CorrectAnswer, Picture
FROM (
SELECT *,
@num := if(@Question = Question, @num + 1, 1) AS q_number,
@Question := Question AS q_dummy
FROM soal
WHERE Difficulty='". $levelStr ."' AND Topic='". $topic ."') AS X
WHERE X.q_number = 1
GROUP BY X.Question
";
Edited by jazzman1

So, I've made a test with a real data similar to @OP I guess :)

 

The table soap:

mysql> SHOW COLUMNS FROM soal;
+---------------+----------------------+------+-----+---------+----------------+
| Field         | Type                 | Null | Key | Default | Extra          |
+---------------+----------------------+------+-----+---------+----------------+
| id            | int(10) unsigned     | NO   | PRI | NULL    | auto_increment |
| Question      | varchar(45)          | NO   |     | NULL    |                |
| Answer1       | varchar(45)          | NO   |     | NULL    |                |
| Answer2       | varchar(45)          | NO   |     | NULL    |                |
| Answer3       | varchar(45)          | NO   |     | NULL    |                |
| Answer4       | varchar(45)          | NO   |     | NULL    |                |
| CorrectAnswer | varchar(45)          | NO   |     | NULL    |                |
| Picture       | varchar(45)          | YES  |     | NULL    |                |
| Difficulty    | smallint(5) unsigned | NO   |     | NULL    |                |
| Topic         | varchar(45)          | NO   |     | NULL    |                |
+---------------+----------------------+------+-----+---------+----------------+

mysql> select * from soal;
+----+---------------------+----------+----------+----------+----------+---------------+----------+------------+--------------+
| id | Question            | Answer1  | Answer2  | Answer3  | Answer4  | CorrectAnswer | Picture  | Difficulty | Topic        |
+----+---------------------+----------+----------+----------+----------+---------------+----------+------------+--------------+
|  1 | what is the apple?  | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |          1 | some topic 1 |
|  2 | what is the apple?  | Answer 1 | Answer   | Answer 3 | Answer 4 | fruit         | some pic |          1 | some topic 1 |
|  3 | what is the apple?  | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |          1 | some topic 1 |
|  4 | what is the cherry? | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |          1 | some topic 2 |
|  5 | what is the cherry? | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |          1 | some topic 2 |
|  6 | what is the cherry? | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |          1 | some topic 1 |
|  7 | what is the orange? | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |          1 | some topic 3 |
|  8 | what is the orange? | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |          1 | some topic 3 |
|  9 | what is the pear?   | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |          1 | some topic 4 |
| 10 | what is the pear?   | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |          1 | some topic 4 |
| 11 | what is the pear?   | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |          1 | some topic 1 |
| 12 | what is the cherry? | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |          1 | some topic 1 |
| 13 | what is the cherry? | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |          1 | some topic 1 |
+----+---------------------+----------+----------+----------+----------+---------------+----------+------------+--------------+

All my proposals should be work if her data structure is similar to mine.

mysql> SELECT id, Question, Answer1, Answer2, Answer3, Answer4, CorrectAnswer, Picture
    -> FROM (
    -> SELECT *,
    -> @num := if(@Question = Question, @num + 1, 1) AS q_number,
    -> @Question := Question AS q_dummy
    -> FROM soal
    -> WHERE Difficulty= 1 AND Topic='some topic 1') AS X
    -> WHERE X.q_number = 1
    -> GROUP BY X.Question;
+----+---------------------+----------+----------+----------+----------+---------------+----------+
| id | Question            | Answer1  | Answer2  | Answer3  | Answer4  | CorrectAnswer | Picture  |
+----+---------------------+----------+----------+----------+----------+---------------+----------+
|  1 | what is the apple?  | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |
|  6 | what is the cherry? | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |
| 11 | what is the pear?   | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |
+----+---------------------+----------+----------+----------+----------+---------------+----------+
3 rows in set (0.00 sec)

mysql> SELECT id, Question, Answer1, Answer2, Answer3, Answer4, CorrectAnswer, Picture
    -> FROM soal
    -> WHERE Difficulty= 1 AND Topic='some topic 1'
    -> GROUP BY Question;
+----+---------------------+----------+----------+----------+----------+---------------+----------+
| id | Question            | Answer1  | Answer2  | Answer3  | Answer4  | CorrectAnswer | Picture  |
+----+---------------------+----------+----------+----------+----------+---------------+----------+
|  1 | what is the apple?  | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |
|  6 | what is the cherry? | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |
| 11 | what is the pear?   | Answer 1 | Answer 2 | Answer 3 | Answer 4 | fruit         | some pic |
+----+---------------------+----------+----------+----------+----------+---------------+----------+
3 rows in set (0.00 sec)

I think, she has to give us a little more information about database and some sample of data too.

@jazzman, i think your language translator is broken.

 

the problem isn't the query. the OP can query for and retrieve the correct rows. the OP is making a QUIZ where the questions are displayed in a random order, without repeating a question. :facewall:

@jazzman, i think your language translator is broken.

 

the problem isn't the query. the OP can query for and retrieve the correct rows. the OP is making a QUIZ where the questions are displayed in a random order, without repeating a question. :facewall:

 

He-he, in fact that my English language translator engine is completely broken, that's why I am here ;)

 

I like you.

Edited by jazzman1

since you are storing the retrieved rows in an array, just use shuffle() to randomize the rows in that array, then loop over the shuffled/random array to output the questions.

if ($ctr>0){
    shuffle($arr);
    foreach($arr as $question){
        echo $question;
    }
}

@jazzman, i don't know what you are reading in this thread, but the op has a number of questions for each difficulty/topic and wants to retrieve them and randomly output them. the problem is to output them without repeating any one question in a set.

 

Hey, thanks for the replies.

 

I did some research about shuffle(), it seems if i use shuffle() to randomize the questions, it seems only reversing the array data, for example array(1,2,3) becomes (3,2,1) or am I taking the wrong conclusion?

 

And about the code you posted, why is it not working for me? I mean, the questions are still repeatable and its not loaded clearly, i mean the answer and question data are all mixed up.

 

Can you give me another suggestion? Or should i post the screenshot?

 

Thanks before..

<?php
  include "databaseconnection.php";
  if ($_GET)
  {
    $topic=$_GET["topic"];
	$level=$_GET["level"];
	$levelStr="";
	if ($level==0)
	{
	  $levelStr="Easy";
	}
	else if ($level==1)
	{
	  $levelStr="Medium";
	}
	else if ($level==2)
	{
	  $levelStr="Hard";
	}
	
	$sqlText="SELECT * FROM soal WHERE Difficulty='". $levelStr ."' AND Topic='". $topic ."'";
	$result=mysql_query($sqlText);

	$ctr=0;
	$arr=null;
	while($row = mysql_fetch_array($result))
	{
	   $arr[$ctr]=$row["SoalID"]."#".$row["Question"]."#".$row["Answer1"]."#".$row["Answer2"]."#".
	              $row["Answer3"]."#".$row["Answer4"]."#".$row["CorrectAnswer"]."#".$row["Picture"];
	   $ctr++;
	}
//    if ($ctr>0)
//	{
//		$totalRand=rand(10,50);
//		for ($i=0;$i<$totalRand;$i++)
//		{
//		   $idx1=rand(0,$ctr-1);
//		   $idx2=rand(0,$ctr-1);
//		   
//		   $res=$arr[$idx1];
//		   $arr[$idx1]=$arr[$idx2];
//		   $arr[$idx2]=$res;
//		}
//		$idx=rand(0,$ctr-1);
//		echo $arr[$idx];
//	}
      if ($ctr>0){
	  shuffle($arr);
	  foreach($arr as $question){
	      echo $question;
	  }
      }
  }
?>

Here's the code to get the question from the database..

I commented my old codes, and changed them to yours..

the questions are still repeatable and its not loaded clearly, i mean the answer and question data are all mixed up.

that code cannot produce repeated questions, unless you have rows in your database table that are repeats.

 

since we only see the information that you post, perhaps you should copy/paste what you see in the browser.

Oh wow.. I think i found the reason why the question is not loaded perfectly if i used shuffle()..

 

The quiz are loaded inside a flash file, to load the question, I connect the array result to it..

 

The code inside the flash file (actionScript) is as follows:

....
var questionID:String = arrContent[0];
var questionL:String = arrContent[1];
var answerS1:String = arrContent[2];
var answerS2:String = arrContent[3];
var answerS3:String = arrContent[4];
var answerS4:String = arrContent[5];
var correctAnswer:String = arrContent[6];
.....

so, if i shuffle() the array, then the string will all be different.. That is why the code is not working as i wanted..

 

Seeing this, it raise another question..

How to randomize the array without changing the array numbers..

:confused:

the code i posted isn't a copy/paste 100% complete tested solution, especially since no one here knew you were even outputting this to flash. it is an example showing how to use shuffle() to sort the rows in your $arr and to loop over the resulting random rows. if your code is doing more than that, it is up to you to take the method shown in the example code and modify it to suite your needs.

Do you have any suggestion in how to make it just like what i need?

 

Would it be work if i do the shuffling inside the sql query rather than in the array?

 

It raised another problem, what kind of query then..

 

:confused:

Edited by puyunk

since you have provided the bigger picture of how you are using the information (outputting one question at a time), the method to prevent duplicates must be different. you must 'remember' which questions have been output and remove them from the 'pool' of questions. which is what i suggested in post #3 in this thread.

 

i would store the SoalID id values in an array in a session variable, then don't select those ids in the query. if $_SESSION['used'] is an array of the id's of the questions that have been output (initialize to an empty array if it doesn't exist), adding the following to the query would only return questions that have not been used -

$ids = implode(',',$_SESSION['used']);
$not_in = empty($ids) ? '' : " AND SoalID NOT IN($ids)";
$sqlText="SELECT * FROM soal WHERE Difficulty='$levelStr' AND Topic='$topic' $not_in";

the previous code i posted would also need to simply output one (the first) element from the shuffled array (i.e. no foreach() loop.)

Edited by mac_gyver
This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.