2016-12-15 46 views
1

TABLE CONSIST PASSAGE AND NORMAL QUESTIONS根據另一列的值按不同列排序

有兩種類型的問題1.通道和2.正常問題。 通常在測試中,我想挑選由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.A,B,C是3名學生Aname是 「阿倫」 B名稱是「Mike」C的名字是「Jhon」(type_id = 1) 誰是C從上面的段落

3.A,B,C是3名學生Aname是「Arun」B名是「Mike」C名是「Jhon」(type_id = 1) 誰是來自以上段落的A

4.Who是Facebook.?(type_id=0的CEO)

形成上述問題,我們將隨機挑選如果問題來在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

我認爲你的數據庫的設計還有待完善,但我要回答你的問題依然存在。

我想我有一個相當簡單的解決方案,我可以在沒有CTE的便攜式SQL中表達。

它的工作原理是這樣的:讓我們把兩個數字的每一行,叫他們major(整數,只是爲了安全起見,讓我們把它十的倍數)和minor(0之間的浮動和1)。對於類型0問題,minor始終爲0.與同一段落有關的每個類型1問題得到相同的major(我們通過與分組子查詢進行連接來完成此操作)。然後,我們通過這兩個值的總和來排序表。

它會很慢,因爲它使用文本字段進行連接。如果每個不同的passage_description都有一個用於連接的整數ID,那將會更好。

我認爲所有的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的問題,則可以在UNION的第一部分取消註釋LIMIT 39。如果您至少需要兩個,那麼請說LIMIT 38,依此類推。與同一段文章有關的所有第一類問題將在一次測試中分組在一起;不能保證數據庫中與該段相關的所有問題都將在測試中,但在上面的評論中,您提到這可能是「破產」的。

被修改:

我加入少量到minor,只是以繞過其中RAND()返回精確爲零的罕見的,但可能的情況。由於major過去幾十年,minor現在可能比一個更大的事實是無關緊要的。

+0

它的工作確定我會升級我的數據庫結構'passage_id'謝謝你我真的appriciate你的時間。 –

+1

我編輯了答案來處理極度低概率的情況,即RAND()完全返回0 __AND__一組通道問題接收到與0類問題相同的整數major。我敢打賭,在你的應用程序的整個生命週期中,這絕不會發生,但儘管如此... – Dario

+0

@AbdulWaheed你說,通道問題(組)應該在0到2之間,並且一個組應該總是完成,除非它超過40個問題的限制。在這個解決方案中,這是不受尊重的,UNION的第一部分的LIMIT似乎不能在mysql 5.7中工作,但是如果它會的話,它只會限制'questions'而不是'groups',所以不能真正控制組被截斷的方式 – 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 

說明前:訂單會= 1項保持TYPE_ID在一起,因爲它會產生對同一通道的問題相同的隨機序列。

警告:除非您在表格中添加passage_id,否則此問題的運行速度會很慢。

編輯:修正了排序(我希望),忘了MYSQL生成0到1之間的隨機數。

+0

通道問題最後也不會出現。 :(見這是我以前的查詢選擇rand()的所有問題:'select * from tbl_testquestion where cat_id ='「。$ cat。」'and subcat_id ='「。$ sub_cat。」'and qu_status ='1' ORDER BY RAND()LIMIT 40'現在我想在其中添加通道問題。 –

+0

你想隨機提問N個問題嗎? –

+0

啊,現在我覺得我理解得更好一點。有沒有辦法確定有多少 –

0

這是mysql的解決方案,
對不起,它不太可讀,因爲mysql不支持像sql-server這樣的CTE。

也許你可以將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

相關問題