Ответ 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)