Mysql Union 2查询包含按和随机的顺序

时间:2019-06-10 14:51:16

标签: mysql random union

我有一个带有以下各列的表: 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())

2 个答案:

答案 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就会给您您真正需要的东西。 [请原谅我查询中的语法错误。]