我有一个带有以下各列的表: id(AI),状态(布尔0或1),创建于(日期时间)
我想获取状态为1的记录,并在DESC上创建它们的顺序,另一个要获取状态为0的随机记录
我按以下方式运行代码,但无法返回正确答案。
(SELECT *
FROM
`Teacher` AS `teacher`
WHERE
`teacher`.`status` = 1 ORDER BY `created_at` desc)
UNION
(SELECT *
FROM
`Teacher` AS `teacher`
WHERE
`teacher`.`status` = 0 ORDER By rand())
答案 0 :(得分:0)
UNION
集运算符正在强制执行“使用文件排序”操作以识别和删除重复项。
UNION ALL
集运算符将连接两个结果集,而无需调用排序操作来识别和删除重复项。
但是只要将UNION
替换为UNION ALL
,我们将依赖无法保证的行为。如果我们需要按特定顺序返回结果,则最外面的查询上应该有一个ORDER BY
子句。
https://dev.mysql.com/doc/refman/8.0/en/union.html
节选
但是,对于单独的
ORDER BY
语句使用SELECT
并不意味着行在最终结果中出现的顺序,因为UNION
缺省情况下会产生一组无序的行。 / p>
...
(如果有人在其中一个表中添加一列,这将导致该查询失败,并且返回的列数不匹配。)
(第二个SELECT中对teacher.status
的引用无效。)
(个人而言,我会在每个集合中添加一个鉴别符列,然后在外部查询的ORDER BY
子句中引用它。我还要在SELECT列表中放弃*
并指定要返回的列。)
我将通过以下方式达到指定的结果:
(
SELECT 'teacher' AS src
, t.fee
, t.fi
, t.fo
, t.fum
FROM `Teacher` t
WHERE t.`status` = 1
)
UNION ALL
(
SELECT 'mission' AS src
, m.one
, m.two
, m.buckle
, m.myshoe
FROM `bouhun`.`missions` m
WHERE m.`status` = 0
)
ORDER
BY src DESC
, CASE src WHEN 'teacher' THEN created_at END DESC
, CASE src WHEN 'mission' THEN RAND() END
*关注*
问题已经编辑,可以更改第二个SELECT中的表名,以便现在它与第一个SELECT中引用的表相同。
进行此更改后,我将只使用一个SELECT。
并避免使用两组UNION
/ UNION ALL
。
我们可以在ORDER BY
子句中添加一些巧妙的表达式。
类似这样的东西:
SELECT t.*
FROM `Teacher` t
WHERE t.status IN (0,1)
ORDER
BY t.status DESC
, IF( t.status=0 , t.created_at , NULL) DESC
, IF( t.status=1 , RAND() , NULL) DESC
答案 1 :(得分:0)
前一段时间我也遇到过类似的问题... 这样的事情应该可以解决。
SELECT * FROM
(
(SELECT ROW_NUMBER() OVER (order by `created_at` desc) AS RowNumber, `status`, id, datetime
FROM
`Teacher` AS `teacher`
WHERE
`teacher`.`status` = 1 ORDER BY `created_at` desc)
UNION
(SELECT ROW_NUMBER() OVER (order by rand()) AS RowNumber, `status`, id, datetime
FROM
`Teacher` AS `teacher`
WHERE
`teacher`.`status` = 0 ORDER By rand())
) order by `status`, RowNumber;
根据给定的条件在表1和表2中添加一个行索引列(RowNumber),以确保状态内的正确排序。
并且我们已经具有状态值(status
)的列。
然后只需按顺序按status
选择*,RowNumber就会给您您真正需要的东西。
[请原谅我查询中的语法错误。]