2016-12-15 41 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

相关问题