Можно ли выбрать случайный столбец в одной строке?

Например, у меня есть 1 вопрос и 5 ответов.

Вопрос:

5+5=?

Answer:

a. 3
b. 4
c. 5
d. 9
e. 10

Здесь примеры данных в базе данных

id  |  question  |  ans1  |  asn2  |  ans3  | ans4  |  correctAns  |
1   |  5+5       |    3   |    4   |    5   |   9   |      10      |

Я хочу рандомизировать вывод ans1, ans2, ans3, ans4 и correctAns.

Возможно ли это? если это пожалуйста, назовите меня.. Спасибо

Ответ 1

Структурные заметки

Хотя этот вопрос может быть интересным, прецедент с ответами на вопрос и предоставленная структура действительно плоха. Это потому, что вы ограничены определенным количеством ответов. Это означает:

  • Все вопросы будут иметь все ответы. Если какой-то вопрос должен содержать только 2 ответа на выбор, тогда - да, будут значения N-2 NULL (здесь N означает количество ответов, в случае выше N=4)
  • Если только один вопрос должен иметь более чем N ответов - тогда да, ALTER ожидает. И это даст больше NULL -s для всех других вопросов.

Я рекомендую изменить структуру. Храните ответы в отдельной таблице с внешним ключом в таблицу родительских вопросов. Этого будет достаточно (и, кроме того, вопрос о случайном выборе будет намного легче разрешить)

Решение вопроса

Однако вопросы, связанные с структурой таблиц, могут быть интересны для решения - и в MySQL такие вопросы классически разрешаются с помощью метаданных INFORMATION_SCHEMA. Чтобы решить проблему только с помощью SQL, вам нужно будет использовать подготовленные заявления. Вот пример таблицы:

mysql> SELECT * FROM test;
+------+----------+------+------+------+------+------------+
| id   | question | ans1 | ans2 | ans3 | ans4 | correctAns |
+------+----------+------+------+------+------+------------+
|    1 | 5+5      |    3 |    4 |    5 |    9 |         10 |
+------+----------+------+------+------+------+------------+
1 row in set (0.00 sec)

Теперь я предполагаю, что столбцы id и question должны быть включены всегда в первое и второе место. Другие столбцы должны быть рандомизированы. Для этого вы можете использовать таблицу INFORMATION_SCHEMA.COLUMNS:

SELECT 
  CONCAT(
    'SELECT id, question, ', 
    GROUP_CONCAT(COLUMN_NAME), 
    ' FROM test') AS s 
FROM 
  (SELECT 
    COLUMN_NAME 
  FROM 
    INFORMATION_SCHEMA.COLUMNS 
  WHERE 
    TABLE_NAME='test' 
    AND 
    TABLE_SCHEMA='test' 
    AND 
    COLUMN_NAME NOT IN ('id', 'question') 
  ORDER BY RAND()) AS randCols;

Как вы можете видеть, этот SQL будет производить другой SQL. Результат будет выглядеть следующим образом:

+---------------------------------------------------------------+
| s                                                             |
+---------------------------------------------------------------+
| SELECT id, question, ans1,ans2,correctAns,ans4,ans3 FROM test |
+---------------------------------------------------------------+
1 row in set (0.00 sec)

Итак, вы можете легко использовать в подготовленном заявлении. Подготовьте переменную:

mysql> set @s=(SELECT CONCAT('SELECT id, question, ', GROUP_CONCAT(COLUMN_NAME), ' FROM test') AS s FROM (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='test' AND TABLE_SCHEMA='test' AND COLUMN_NAME NOT IN ('id', 'question') ORDER BY RAND()) AS randCols);
Query OK, 0 rows affected (0.01 sec)

Используйте его для оператора:

mysql> prepare stmt from @s;
Query OK, 0 rows affected (0.00 sec)
Statement prepared

И, наконец, выполните его:

mysql> execute stmt;
+------+----------+------------+------+------+------+------+
| id   | question | correctAns | ans1 | ans2 | ans4 | ans3 |
+------+----------+------------+------+------+------+------+
|    1 | 5+5      |         10 |    3 |    4 |    9 |    5 |
+------+----------+------------+------+------+------+------+
1 row in set (0.00 sec)

Ответ 2

Лучше сначала получить результат и поместить его в массив, а затем вы можете легко перетасовать его, что-то вроде этого:

$query = "SELECT ans1, asn2, ans3, ans4, correctAns FROM table_name WHERE id=1";
$res = mysql_query($query);
$answers = mysql_fetch_array($res);
shuffle($answers);

Затем итерацию через $answers в соответствии с нормалью.

Ответ 3

Для чистого ответа mysql:

SELECT ans FROM
(SELECT ans1 as ans,questionid FROM questions)
UNION
(SELECT ans2 as ans,questionid FROM questions)
UNION
(SELECT ans3 as ans,questionid FROM questions)
UNION
(SELECT ans4 as ans,questionid FROM questions)
UNION
(SELECT correct as ans,questionid FROM questions)
WHERE questionid = $questionid
ORDER BY RAND()

порядок по rand() используется, чтобы порядок строк возвращался случайным

Лучший способ

Лучший способ сделать это - изменить структуру столбцов на:

Таблица Вопрос:

| id | name | 

Таблица anser:

| question_id | answer |

С данными:

id   | name
1    | 5+5

question_id | answer
1           | 4
1           | 3
1           | 9
1           | 5
1           | 10

то вы можете использовать:

SELECT answer
FROM answer
WHERE question_id = $question_id
ORDER BY RAND()

Ответ 4

Вы можете использовать функцию shuffle.

Используйте код, похожий на:

$sql = "select ans1,ans2,ans3,ans4  from questions where id=$questionId";
$result = $mysqliconnection->query($sql);
$row = $result->fetch_assoc();
shuffle($row);

Теперь row содержит перетасованный массив результатов для вопроса с заданным id.

Ответ 5

Вы можете взять все ответы на этот вопрос, например

$query="SELECT ans1,ans2,ans3,ans4,correctAns FROM yourTable WHERE id=1";

А потом просто скажите PHP, чтобы отобразить случайный ответ.

$mysqli = new mysqli("localhost", "my_user", "my_password", "my_db");
$result = $mysqli->query($query);
$row = $result->fetch_array(MYSQLI_NUM);
$randomAnswer=$row[rand(0,4)];
echo $randomAnswer;