Update:
I fixed the previous problems. Now the codes are up-dated. Results are unique and IDs are right. But new problem:
The amount of result rows is often less than requirement (8).
Because I added CREATE UNIQUE INDEX topicid on rands (topicid);
to deny the repeated inserts in SQL layer; the loop - 1 regardless the insert is denied. I am now looking for a method like: IF insert successful THEN cnt-=1. Do you know any way to do this in SQL layer? Thanks.
I have a table called topictable which contains two coulmns-topicid and topic. I want to get 8 random rows from the table without repeats. I stole the code from here and modified into getting two column results. But I have two problems with it. 1. It is not distinct; 2. the id is wrong (I catch the wrong random id somehow).
DELIMITER $$
DROP PROCEDURE IF EXISTS get_rands$$
CREATE PROCEDURE get_rands(IN cnt INT)
BEGIN
DROP TEMPORARY TABLE IF EXISTS rands;
CREATE TEMPORARY TABLE rands ( topicid INT ,topic VARCHAR(128) );
CREATE UNIQUE INDEX topicid on rands (topicid);
loop_me: LOOP
IF cnt < 1 THEN
LEAVE loop_me;
END IF;
INSERT INTO rands
SELECT topictable.topicid,topictable.topic
FROM topictable
JOIN (SELECT (RAND()*(SELECT MAX(topictable.topicid) FROM topictable)) AS id) AS choices
WHERE topictable.topicid >= choices.id
LIMIT 1;
SET cnt = cnt - 1;
END LOOP loop_me;
END$$
DELIMITER ;
I use the following function in php to execute the script.
function pickrandomtopics($amountoftopics,$dbh){
try {
$randtable="CALL get_rands($amountoftopics)";
$dbh->exec("$randtable");
$topictemp = $dbh->query('SELECT * FROM rands');
$topics = $topictemp->fetchAll(PDO::FETCH_ASSOC);
}
catch(PDOException $e) {
echo $e->getMessage();
}
return $topics;}
Thanks for your helps.
Sorry, I didn't make it clear. All the topics in this table are unique in the beginning. But they might duplicate at the end, because the function picks the row randomly from time to time, sometime it just pick a same row twice. Thanks for your help.
Thank @tereško. the
CONTINUE HANDLER FOR SQLSTATE '23000'
catches "not unique" errors and correct cnt back by +1.To solve one of your problem I think this might help - Using SubQuery
.This is just a guide line and not the actual query