how to get Unique Random number in php - php

I am trying to develop a Computer Base Test (CBT) software on PHP.
I want it to retrieve question from MYSQL DATABASE randomly where I have 100 questions in the database.
But using <? rand(1,100); ?> there is real assurance that it may select same question at same session.
How do I select a unique random number in a session?

You can use RAND() to get random questions from database. And to take-care of uniqueness of questions you can use IN keyword while selecting new question from database. Means you need to keep track of all old Questions to check IN.
OR you can get all unique questions from database using RAND() at once and use those questions for that session.

I don't know this solves your problem with php. But with Mysql rand() you can retrieve random questions from db.
SELECT * FROM yourtable ORDER BY RAND();
If you want 10 random rows out of 100 rows
SELECT * FROM yourtable ORDER BY RAND() LIMIT 10;

Related

how get random questions from database include Categories?

Hallo i try to make a simple quiz application in php based on math tests from many years. I have database with such columns:
-id
-pytanie
-a
-b
-c
-d
-poprawna
-rok_id
-typ_id
I use rand function to get random id and next i use this in sql answer to get random question.
However id dont know how get radnom question for example random one question include yera_id=1
Firstly i use $numer=rand(1,1800)
My sql select is such as\
select pytanie, a,b,c,d, nazwa, rok_liczba, nazwa_typu, poprawna from pytania left join rok on rok.id= pytania.rok_id left join typ on typ.id=pytania.typ_id where typ_id=1 and pytania.id=".$numer.""
When i add to sql select ,,where year_id=1" i must click many time to hit when rand get 1 beacuse otherwise i dont get any resoult. It possible to rand from records ho are resoult a sql answer ?
You are computing a random number outside of the database then using it as a filter: but there is no guarantee that you have a record that matches your random value and the other filter on the question type.
I would recommend doing the random sort in the query itself. This should be as simple as adding this at the end of your query:
select ...
from ...
where typ_id = 1
order by rand() limit 1
Note that the exact syntax may vary across databases - the above is MySQL syntax.

MySql -- How to keep a record of used entries?

I have an application (More likely a quiz app) where i have saved all my 1000 quizzes in MySQL database, I want to retrieve a random question from this table when a user request one, I can easily do it using the RAND() function in MySQL.. my problem is , I don't want to give the same question two or more times to a user, how can i keep a record of retrieved questions? Do I have to create tables for each and every users? won't that increase the load time?? please help me, any help would be a big favor ..
-regards
If you want it for a short time, use the user's $_SESSION for that.
If you need the long term ( say tomorrow, not to ask the same questions) - you'll have to create additional table for usersToQuestions, where you'll store the user id and the questions the user had been already asked.
Retrieving a question in both cases would require a simple IN condition:
SELECT * FROM questions
WHERE id not IN ('implode(",", $_SESSION["asked"])')
SELECT * FROM questions
WHERE id not IN (
SELECT question_id FROM questions2users WHERE userid = 123
)
my problem is , I don't want to give the same question two or more times to a user,
how can i keep a record of retrieved questions? Do I have to create tables for each
and every users? won't that increase the load time?
Yes, but possibly not so much.
You keep a single extra table with userId, questionId and insert there the questions already asked to the various users.
When you ask question 123 to user 456, you run a single INSERT
INSERT INTO askedQuestions (userId, questionId) VALUES (456, 123);
Then you extract questions from questions with a LEFT JOIN
SELECT questions.* FROM questions
LEFT JOIN askedQuestions ON (questions.id = askedQuestions.questionId AND askedQuestions.userId = {$_SESSION['userId']} )
WHERE askedQuestions.userId IS NULL
ORDER BY RAND() LIMIT 1;
if you keep askedQuestions indexed on (userId, questionId), joining will be very efficient.
Notes on RAND()
Selecting on a table like this should not done with ORDER BY RAND(), which will retrieve all the rows in the table before outputting one of them. Normally you would choose a questionId at random, and select the question with that questionId, and that would be waaaay faster. But here, you have no guarantee that the question has not been already asked to that user, and the faster query might fail.
When most questions are still free to ask, you can use
WHERE questions.questionId IN ( RAND(N), RAND(N), RAND(N), ... )
AND askedQuestions.userId IS NULL LIMIT 1
where N is the number of questions. Chances are that at least one of the random numbers you extract will still be free. The IN will decrease performances, and you will have to strike a balance with the number of RANDs. When questions are almost all asked, chances of a match decrease, and your query might return nothing even with many RANDs (also because RANDs will start yielding duplicate IDs, in what is known as the Birthday Paradox).
One way to achieve the best of both worlds could be to fix a maximum number of attempts, say, three (or better still, based on the number of questions left over).
For X times you generate (in PHP) a set of Y random ids betweeen 1 and 1000, and try to retrieve (userId, questionId) from askedQuestions. The table is thin and indexed, so this is really fast. If you fail, then the extracted questionId is random and free, and you can run
SELECT * FROM questions WHERE id = {$tuple['questionId']};
which is also very fast. If you succeed X times, i.e., for X times, all Y random questionIds are registered as being already asked, then you run the full query. Most users will be served almost instantly (two very quick queries), and only a few really dedicated users will require more processing. You might want to set some kind of alerting to warn you of users running out of questions.
One solution is to add an ID column in the question table and when you serve it to a user you check that ID with the list of questions that you served the user.
You can use in memory data structure like List to keep track of the questions that are served to a particular user. This way, you only need array of Lists instead of tables to get the job done.

How to echo random row from database? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
MySQL: How to retrieve a random row or multiple random rows?
Pull 5 random records from mysql database
I have a large list of domains in my database in the table "list" under the column "website".
There are about 140 million rows and I just need to know how to echo a random one.
Basically like this:
<?php include('directory/database.php'); ?>
WHATEVER CODE WORKS FOR GETTING A RANDOM DOMAIN FROM THE DATABASE
<?php
echo $domain;
?>
There's just a huge amount of records so I need to know the quickest way to just have one of them randomly selected and displayed on a page. Thanks!
You definitely don't want to use ORDER BY RAND(). MySQL has to build a temporary table. If your table has a unique id column, something like this is much better:
SELECT * FROM `table`
WHERE id >= (SELECT FLOOR( MAX(id) * RAND()) FROM `table` )
ORDER BY id LIMIT 1;
See this blog post for other approaches that work well in php.
Note: This simply repeats my answer on this thread.

MySQL vs PHP when retrieving a random item

which is more efficient (when managing over 100K records):
A. Mysql
SELECT * FROM user ORDER BY RAND();
of course, after that i would already have all the fields from that record.
B. PHP
use memcached to have $cache_array hold all the data from "SELECT id_user FROM user ORDER BY id_user" for 1 hour or so... and then:
$id = array_rand($cache_array);
of course, after that i have to make a MYSQL call with:
SELECT * FROM user WHERE id_user = $id;
so... which is more efficient? A or B?
The proper way to answer this kind of question is to do a benchmark. Do a quick and dirty implementation each way and then run benchmark tests to determine which one performs better.
Having said that, ORDER BY RAND() is known to be slow because it's impossible for MySQL to use an index. MySQL will basically run the RAND() function once for each row in the table and then sort the rows based on what came back from RAND().
Your other idea of storing all user_ids in memcached and then selecting a random element form the array might perform better if the overhead of memcached proves to be less than the cost of a full table scan. If your dataset is large or staleness is a problem, you may run into issues though. Also you're adding some complexity to your application. I would try to look for another way.
I'll give you a third option which might outperform both your suggestions: Select a count(user_id) of the rows in your user table and then have php generate a random number between 0 and the result of count(user_id) minus 1, inclusive. Then do a SELECT * FROM user LIMIT 1 OFFSET random-number-generated-by-php;.
Again, the proper way to answer these types of questions is to benchmark. Anything else is speculation.
The first one is incredibly slow because
MySQL creates a temporary table with
all the result rows and assigns each
one of them a random sorting index.
The results are then sorted and
returned.
It's elaborated more on this blog post.
$random_no = mt_rand(0, $total_record_count);
$query = "SELECT * FROM user ORDER BY __KEY__ LIMIT {$random_no}, 1";

How can I generate unique random numbers in PHP?

I am working on a MCQ module and I need to fetch random questions from my database. The problem is that I seem to get duplicates.
If you're fetching them from database, use SQL to do your job. e.g. fetching 20 random questions (without repeating):
SELECT * FROM questions ORDER BY RAND() LIMIT 20
Sounds like you want to shuffle the questions, not randomize access to them. So your algorithm would be something like this.
Get the all question (or question keys) you want to display.
Shuffle them
Retrieve/ display in them in the shuffled order
for shuffling check out: Fisher-Yates shuffle algorithm
If you're using MySql and you have reasonable small amount of data, you can use ORDER BY RAND()
See Do stateless random number generators exist?
Any sequence of pseudo-random numbers will eventually repeat. How you obtain your pseudo-random numbers?
Without any more info i can suggest a rudimentary solution. (but please update your question with more info)
I'm guessing you have users, because then you could save into a table (be it temporary or not), what questions said user has already gotten.
If you don't have users, you can use the SESSION_ID as a user identifier for that user.
So when you fetch a question for the first time, and the user answers it, it saves the info you need to save, and then the user's id and the question's id into a table.
When fetching the next question, you do a check to see if the user has that question id in this new table.
If you have a very large number of rows you can add a column to the table which stores a number between 0 and 1 and then fetch with a query:
SELECT * FROM `mytable` WHERE `randcolumn` > RAND() LIMIT 20
This means that your database doesn't have to randomly order the entire table to provide just 20 rows.

Categories