MichaelRushton's method can optimize to
SELECT id1, id2, id3, id4 FROM (
SELECT t1.id id1, t2.id id2, t3.id id3, t4.id id4
FROM tt t1
INNER JOIN tt t2 ON t2.id !=t1.id
INNER JOIN tt t3 ON t3.id !=t1.id AND t3.id !=t2.id
INNER JOIN tt t4 ON t4.id !=t1.id AND t4.id !=t2.id AND t4.id !=t3.id
ORDER BY RAND()) AS t
GROUP BY t.id1
ORDER BY NULL;
other method:
SELECT (@a:=`id`) AS a
,(@b:=(SELECT `id` FROM `tt` WHERE id NOT IN (@a) ORDER BY RAND() LIMIT 1)) AS b
,(@c:=(SELECT `id` FROM `tt` WHERE id NOT IN (@a,@b) ORDER BY RAND() LIMIT 1)) AS c
,(@d:=(SELECT `id` FROM `tt` WHERE id NOT IN (@a,@b,@c) ORDER BY RAND() LIMIT 1)) AS d
FROM `tt` AS t,(SELECT @a,@b,@c,@d) AS t2
ORDER BY t.id;
or
SELECT a, b, c,(SELECT `id` FROM `tt` AS td WHERE id NOT IN (a,b,c) ORDER BY RAND() LIMIT 1) AS d
FROM (SELECT a, b,(SELECT `id` FROM `tt` AS tc WHERE id NOT IN (a,b) ORDER BY RAND() LIMIT 1) AS c
FROM (SELECT a,(SELECT `id` FROM `tt` AS tb WHERE id NOT IN (a) ORDER BY RAND() LIMIT 1) AS b
FROM (SELECT `id` AS a FROM `tt` AS ta) AS tt1
) AS tt2
) AS tt3
ORDER BY a;
but its efficiency is very low!