2016-12-15 8 views
1

TABLE CONSIST PASSAGE AND NORMAL QUESTIONSСортировка по другому столбцу в зависимости от значения другого столбца

Есть два типа вопросов там 1.Passage и 2.Normal вопросов. Обычно в тесте я хочу выбрать случайные вопросы, которые состоят из type_id=0, в том случае, если вопрос type=1 возникает, следующий вопрос должен быть связан с этим вопросом (вопрос о понимании должен быть последовательным). Используя приведенный ниже запрос я могу получить вопросы

SELECT *  
FROM tbl_testquestion 
ORDER BY 
    CASE 
     WHEN type_id=0 THEN RAND() 
     WHEN type_id=1 THEN qu_id 
    END ASC 

все проходные вопросы приходят в последний раз

и у меня есть предел 40 вопросов для теста и в таблице у меня есть 50 вопросы прохождения и 70 нормальных вопросов.

Как я могу написать запрос для вызова вопросов прохода между нормальными вопросами.

ПРИМЕР

1.Who является президентом America.?(type_id=0)

2., В, С 3 студента Aname является "Арун" имя Б «Mike» C называется «Jhon» (type_id = 1) , который является C из вышеуказанного прохода.

3.A, B, C - это 3 студента. Aname is «Arun» B name is «Mike» C name is «Jhon» (type_id = 1) , который является A из вышеуказанного прохода

4.Who является исполнительным директором Facebook.?(type_id=0)

Сформировать Над вопрос, который мы выберем случайным образом, если вопрос приходит в том, что rand() не проблема, когда вопрос приходит в rand() следующий вопрос должен быть последовательным. это означает, что следующий вопрос должен быть после этого пассажа вопросы завершения он должен вернуться к rand() функциональности

+1

Зачем вам нужен случайный сортировка?Вы можете просто использовать ORDER BY qu_id – GrApDev

+2

@Abdul Waheed, вы можете упорядочить строки в своей таблице так, как вам нужно, и использовать ORDER BY qu_id :), но в этом случае вам нужно добавить новый номер столбца в таблице и ваш запрос будет выглядеть одинаково: SELECT * FROM tbl_testquestion WHERE NUMBER_OF_TICKET = RAND() ORDER BY qu_id – GrApDev

+0

если вопрос прохода состоит из 3 вопросов: 1) в лимите 40 вопросов он рассчитан на 1 вопрос или на 3 вопроса? 2) если группа из 3 вопросов упорядочена в примере как 38-е, может ли она быть разбита и отрезана последним из трех или группа должна быть сохранена? 3) если группа должна соблюдаться, ограничение станет, то есть, 41 вопрос или должно отменять нормальные вопросы выше? 4) если нет нормальных вопросов для снятия? – MtwStark

ответ

4

Я думаю, что дизайн вашей базы данных должен быть улучшен, но я собираюсь ответить ваш вопрос в его нынешнем виде.

Я думаю, что у меня довольно простое решение, которое я могу выразить в переносном SQL без CTE.

Он работает следующим образом: давайте назначим два числа к каждой строке, назовем их major (целое число, на всякий случай давайте сделаем это кратно десяти) и minor (поплавок между 0 и 1). Для вопросов типа 0 minor всегда равен 0. Каждый вопрос типа 1, относящийся к одному и тому же пропуску, получает то же самое major (мы делаем это с объединением с сгруппированным подселектом). Затем мы заказываем таблицу по сумме двух значений.

Он будет медленным, потому что он соединяется с использованием текстового поля. Было бы лучше, если бы каждый отдельный passage_description имел целочисленный идентификатор, который будет использоваться для соединения.

Я полагаю, что все типа 0 вопросов есть пустой или нулевой passage_description, в то время как тип 1 вопросы имеют их непустое (это не имело бы никакого смысла иначе.)

Я предполагаю, что у вас есть RAND() функции, которое дает плавающие значения между 0 и 1.

Здесь мы идем:

SELECT u.qu_id, u.type_id, 
     u.passage_description, u.passage_image, 
     u.cat_id, u.subcat_id, 
     u.question, u.q_instruction, u.qu_status 
    FROM (
    SELECT grouped.major, RAND()+0.001 AS minor, t1.* 
    FROM tbl_testquestion t1 
    JOIN (SELECT 10*FLOOR(1000*RAND()) major, passage_description 
      FROM tbl_testquestion WHERE type_id = 1 
      GROUP BY passage_description) grouped 
    USING (passage_description) 
    -- LIMIT 39 
    UNION 
    SELECT 10*FLOOR(1000*RAND()) major, 0 minor, t0.* 
    FROM tbl_testquestion t0 WHERE type_id = 0 
) u ORDER BY u.major+u.minor ASC LIMIT 40; 

С вышеуказанным запросом без изменений, все еще существует небольшая вероятность того, что вы получите вопросы только одного типа. Если вы хотите быть уверены, что у вас есть хотя бы один вопрос типа 0, вы можете раскомментировать номер LIMIT 39 в первой части UNION. Если вы хотите хотя бы два, скажите LIMIT 38 и так далее. Все вопросы типа 1, относящиеся к одному и тому же проходу, будут сгруппированы в один тест; не гарантируется, что все вопросы в базе данных, связанные с этим проходом, будут в тесте, но в комментарии выше вы упоминаете, что это может быть «сломано».

Отредактировано:

я добавил небольшую сумму minor, просто обойти редкое, но возможный случай, в котором RAND() возвращает в точности равна нулю. Поскольку major идет десятками, то факт, что minor теперь может быть больше одного, не имеет значения.

+0

Он работал уверен, что я обновляю свою структуру базы данных с помощью 'pass_id', спасибо, что я действительно appriciate ваше время. –

+1

Я отредактировал ответ, чтобы иметь дело с крайне маловероятным случаем, когда 'RAND()' вернул ровно 0 __AND__ группа вопросов прохода получила одно и то же целое число 'major' как вопрос типа 0. Бьюсь об заклад, это никогда не происходило бы на протяжении всего жизненного цикла вашего приложения, но тем не менее ... – Dario

+0

@AbdulWaheed вы сказали, что вопросы (группы) должны проходить от 0 до 2 и что группа должна быть всегда завершена, за исключением случаев, когда она превышает ограничение на 40 вопросов. В этом решении это не соблюдается, LIMIT в 1-й части UNION, похоже, не работает в mysql 5.7, но если это произойдет, он ограничивает только «вопросы» не «группами», поэтому не существует реального контроля над тем, как группы усекаются. – MtwStark

0

Используйте следующий, я не проверял это так, если есть какие-либо ошибки, пожалуйста, доложите, я исправлю их , $ r - случайное значение, созданное PHP для этого запроса. Вы можете сделать $ r = rand(); перед вызовом запроса

SELECT * FROM (
    UNION((
     SELECT *, RAND()*(SELECT COUNT(*) FROM tbl_testquestions) as orderid 
      FROM tbl_testquestion 
      WHERE type_id=0 
      ORDER BY orderid 
      LIMIT 20 
     ),(
     SELECT *, MD5(CONCAT('$r', passage_description)) as orderid 
      FROM tbl_testquestion 
      WHERE type_id=1 
      ORDER BY orderid 
      LIMIT 20 
    )) 
) AS t1 
ORDER BY orderid 

Объяснения: OrderID будет держать type_id = 1 записи вместе, как он будет производить ту же случайную последовательность для одних и тех же проходных вопросов.

Предупреждение: Если вы не добавите pass_id к столу, этот вопрос будет работать довольно медленно.

Редактировать: Исправлен заказ (надеюсь), забыл, что MYSQL генерирует случайные числа от 0 до 1.

+0

Вопросы прохода также не приходят последним. :(см. это мой предыдущий запрос, чтобы выбрать весь вопрос rand(): 'select * from tbl_testquestion, где cat_id = '". $ cat. "' и subcat_id = '". $ sub_cat. "' и qu_status = '1' ORDER BY RAND() LIMIT 40' теперь я хочу добавить в него вопросы о прохождении. –

+0

Вам нужны случайные вопросы, за которыми следуют вопросы о пропуске? –

+0

А теперь я думаю, что я понял немного лучше. Есть ли способ определить, сколько вопросы в серии вопросов серии? Не говорите мне из текста вопроса. –

0

Это решение для mysql,
извините, что это не так читаемо, потому что mysql не поддерживает CTE, как sql-server.

Возможно, вы можете сравнить с синтаксисом sql-server CTE на дне, чтобы лучше понять, как это работает.

select 
    d.* 
    , o.q_ix, rnd_ord -- this is only for your reference 
from (
     select *, floor(rand()*1000) as rnd_ord -- this is main order for questions and groups 
     from (

      select * from (
       select 
        (@r1 := @r1 - 1) as q_ix, -- this is row_number() (negative so we can keep group separated) 
        passage_description, 0 qu_id, type_id 
       from (
        select distinct passage_description, type_id 
        from tbl_testquestion, 
        (SELECT @r1 := 0) v, -- this is the trick for row_number() 
        (SELECT @rnd_limit := -floor(rand()*3)) r -- this is the trick for dynamic random limit 
        where type_id=1 
       ) p 
       order by passage_description -- order by for row_number() 
      ) op 
      where q_ix < @rnd_limit 

      union all 

      select * from (
       select 
        (@r2 := @r2 + 1) as q_ix, -- again row_number() 
        '' as passage_description, qu_id, type_id 
       from tbl_testquestion, 
       (SELECT @r2 := 0) v -- var for row_number 
       where type_id=0 
       order by qu_id -- order by for row_number() 
      ) oq 

     ) q 
) o 
-- look at double join for questions and groups 
join tbl_testquestion d on 
    ((d.passage_description = o.passage_description) and (d.type_id=1)) 
    or 
    ((d.qu_id=o.qu_id) and (d.type_id=0)) 
order by rnd_ord 
limit 40 

и это более читаемый синтаксис SQL-сервер:

;with 
p as ( 
    -- select a random number of groups (0-2) and label groups (-1,-2) 
    select top (abs(checksum(NEWID())) % 3) -ROW_NUMBER() over (order by passage_description) p_id, passage_description 
    from (
     select distinct passage_description 
     from d 
     where type_id=1 
    ) x 
), 
q as (
    -- label questions (1..n) 
    select ROW_NUMBER() over (order by qu_id) q_ix, qu_id 
    from d 
    where type_id=0 
), 
o as (
    -- calculate final order 
    select *, ROW_NUMBER() over (order by newid()) rnd_ord 
    from (
     select p.q_ix, passage_description, 0 qu_id from p 
     union all 
     select q.q_ix, '', qu_id from q 
    ) x 
) 
select top 40 
    d.* 
    , o.rnd_ord, o.q_ix 
from o 
join d on 
    ((d.passage_description = o.passage_description) and (d.type_id=1)) 
    or 
    ((d.qu_id = o.qu_id) and (d.type_id=0)) 
order by 
    rnd_ord 

что все

+0

было бы вежливо объяснить причины для downvote .. – MtwStark

Смежные вопросы