Сформулировать запрос: количество правильных ответов
От: Аноним  
Дата: 29.09.07 00:47
Оценка:
Дано: база — sqlite3 (более-менее стандартный sql, вложенные запросы поддерживает, из джойнов — только inner и left outer).

Структура таблиц (та часть, которая относится к делу):

questions
  id

sessions
  id

question2session
  question_id
  session_id

(есть вопросы для тестов, есть "тестовые сессии", в question2session — отношение "на какие вопросы отвечал студент проходя данную сессию")

choices
  id
  question_id
  is_right

варианты ответа на вопрос. вариантов может быть сколько угодно (2 и больше), из них любое количество может быть верными (is_right).

answers
  session_id
  question_id
  choice_id

ответы студента. если ответ с данным choice_id присутствует в базе, значит студент выбрал этот вариант из вариантов ответа.

ВНИМАНИЕ, ВОПРОС: сформировать запрос "количество правильных ответов в данной сессии". т.е. количество таких вопросов, для которых набор "правильные ответы на данный вопрос" (select id from choices where question_id = this_question and is_right = true) точно совпал с набором "ответы студента на данный вопрос" (select choice_id from answers where question_id = this_question and session_id = this_session).

на данный момент делается глупо: для каждого вопроса в сессии (select question_id from questions join question2session where question2session.session_id = this_session) выполняются описанные ранее запросы (все правильные ответы, все ответы студента) и результаты сравниваются как массивы. Скорость чудовищна.

соответственно, ищется один из вариантов ответа:
* вот единственный запрос, который это делает
* вот так надо изменить структуру базы; и тогда вот единственный запрос, который это сделает
* и др. варианты ускорения (добавь индексы, используй вот эти 2, 3, 4 запроса — в общем, практически любые идеи)

спасибо!
Re: Сформулировать запрос: количество правильных ответов
От: Kvazimodo75  
Дата: 01.10.07 06:06
Оценка:
Здравствуйте, Аноним, Вы писали:

А>соответственно, ищется один из вариантов ответа:

А>* вот единственный запрос, который это делает
А>* вот так надо изменить структуру базы; и тогда вот единственный запрос, который это сделает
А>* и др. варианты ускорения (добавь индексы, используй вот эти 2, 3, 4 запроса — в общем, практически любые идеи)

Для начала, если поле в ответах, отвечающее за студента? (просто спросил, ничего личного)

select count(id)
from choices
where is_right = true and question_id = @QID

select count(choice_id)
from answers
where question_id = @QID
and choise_id in (select id
from choices
where is_right = true and question_id = @QID)

Далее сравниваются два числа и пожалуйста. т.е. по массиву надо пробежаться всего count(question_id) раз, вызовов sql будет count(question_id)*2.

сессию добавить во все подзапросы надо будет

Поддерживаются ли хранимки и временные таблицы?


А>спасибо!


не за что.
Re: Сформулировать запрос: количество правильных ответов
От: denis.zhdanov Россия http://denis-zhdanov.blogspot.com/
Дата: 01.10.07 06:10
Оценка:
Здравствуйте, Аноним, Вы писали:

А>...


А>соответственно, ищется один из вариантов ответа:

А>* вот единственный запрос, который это делает
А>...


Что-то типа

select 
    session_id, 
    question_id
from 
    answers  
join choices 
    on answers.choice_id = choices.id 
where 
    choices.is_right = 'y' 
group by 
    session_id, 
    question_id
having 
    count(*) = (
                  select 
                      count(*) 
                  from 
                      choices 
                  where 
                      is_right = 'y' 
                  group by 
                      question_id
                )
http://denis-zhdanov.blogspot.com
Re: FIY - вопрос решен
От: Аноним  
Дата: 02.10.07 05:08
Оценка:
спасибо всем поучаствовавшим! Решение, как водится, подтвердило мое убеждение, что если требуется настолько сложный запрос — что-то не так с моделью данных. Короче говоря, в результате оказалось
* "количество верных ответов в сессии" нужно вычислять для каждой сессии всего 1 раз — по закрытию сессии
* answer должен хранить каков, собственно, был вариант, и был ли он правильным.
(оба изменения — потому что вопросы и ответы могут поменяться после того, как какие-то студенты уже прошли тестирование; и результаты тестирования для этих студентов не должны зависеть от будущих изменений).

В результате, таблица answers приобрела следующий вид:

id,
session_id,
question_id,
choice_id,
choice_text,
choice_value, -- is_right из таблицы choices
selected      -- выбрал ли студент этот вариант


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

Вычисление же количества правильных ответов делается 2 довольно тривиальными запросами (не слишком оптимально, можно, наверное, и в один запрос свести, но учитывая, что это вычисление проводится 1 раз — по завершению студентом тестирования — и так хорошо):

1. найти все вопросы в этой сессии:
select distinct question_id from answers where session_id = @current_session

2. найти все вопросы, на которые неверно отвечено "да" или "нет":
select distinct question_id from answers 
where 
  session_id = @current_session and 
  (choice_value = 't' and selected = 'f'
    or
  choice_value = 'f' and selected = 't')


3. вычесть множество (2) из множества (1)
4. вернуть размер результирующего множества.

подозреваю, что это все тривиально сводится к одному запросу, но уже лень думать, скорость меня устраивает и так
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.