Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/253.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 根据另一列的值按不同列排序_Php_Mysql_Sql_Random_Sequence - Fatal编程技术网

Php 根据另一列的值按不同列排序

Php 根据另一列的值按不同列排序,php,mysql,sql,random,sequence,Php,Mysql,Sql,Random,Sequence,这里有两种类型的问题1.短文和2.普通问题。 通常在测试中,我想随机选择由type\u 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

这里有两种类型的问题1.短文和2.普通问题。 通常在测试中,我想随机选择由
type\u 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.谁是美国总统

2.A、B、C是3名学生,A名是“阿伦”,B名是“迈克”,C名是“约翰”(类型id=1) 谁是上文中的C

3.A、B、C是3名学生,A名是“阿伦”,B名是“迈克”,C名是“约翰”(type_id=1) 谁是以上文章的作者

4.谁是Facebook的首席执行官?(type_id=0)


从上述4问题中,如果问题1出现在
rand()
中,则我们将随机选择问题2出现在
rand()
中,则下一个问题应该是顺序问题。这意味着下一个问题应该是3在这篇文章的问题完成后,它应该切换回
rand()
功能性使用以下内容,我还没有测试过,因此,如果有任何错误,请报告,我会更正它们$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条目放在一起,因为它将为相同的文章问题生成相同的随机序列

警告:除非您将文章id添加到表格中,否则此问题将非常缓慢


编辑:修复了排序问题(我希望如此),忘记了MYSQL会生成0到1之间的随机数。

使用以下方法,我没有测试过,因此,如果有任何错误,请报告,我会更正它们$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条目放在一起,因为它将为相同的文章问题生成相同的随机序列

警告:除非您将文章id添加到表格中,否则此问题将非常缓慢


编辑:修复了排序问题(我希望如此),忘记了MYSQL会生成0到1之间的随机数。

这是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

就这些

这是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

仅此而已

我认为数据库的设计应该改进,但我将按现状回答您的问题

我想我有一个相当简单的解决方案,我可以在不使用CTE的情况下用可移植SQL来表示

它是这样工作的:让我们给每一行分配两个数字,称它们为
major
(一个整数,为了安全起见,让我们将其设为10的倍数)和
minor
(0和1之间的浮点)。对于类型为0的问题,
minor
始终为0。与同一篇文章相关的每一个类型1问题都会得到相同的
主调
(我们通过一个连接和一个分组的子选择来实现这一点)。然后,我们根据两个值的总和对表格进行排序

它会很慢,因为它使用文本字段进行连接。如果每个不同的
passage\u description
都有一个用于连接的整数id,那就更好了

我假设所有类型0的问题都是空的或空的
段落描述
,而类型1的问题都是非空的(否则就没有意义了)

我假设您有一个
RAND()
函数,它生成0到1之间的浮点值

我们开始:

对于上面的查询,如果不进行修改,您仍然很可能只得到一种类型的问题。如果您想确保您至少有一个类型0问题,您可以取消注释
联合体第一部分的
限制39
。如果你至少想要两个,那么说
限制38
,依此类推。与同一篇文章相关的所有类型1问题将在一次测试中分组;这并不能保证数据库中与这篇文章相关的所有问题都会出现在测试中,但在上面的评论中,你提到了这可能会被“打破”

编辑:


我在
minor
中添加了少量,只是为了绕过RAND()返回零的罕见但可能的情况。由于
major
增加了十倍,因此
minor
现在可能大于一的事实无关紧要。

我认为数据库的设计应该改进,但我将按现状回答您的问题

我想我有一个相当简单的解决方案,我可以在不使用CTE的情况下用可移植SQL来表示

它是这样工作的:让我们给每一行分配两个数字,称它们为
major
(一个整数,为了安全起见,让我们将其设为10的倍数)和
minor
(0和1之间的浮点)。对于类型为0的问题,
minor
始终为0。与同一篇文章相关的每一个类型1问题都会得到相同的
主调
(我们通过一个连接和一个分组的子选择来实现这一点)。然后,我们根据两个值的总和对表格进行排序

它会很慢,因为它使用文本字段进行连接。如果每个地区