【问题标题】:Mysql union 2 queries containing order by and random包含 order by 和 random 的 Mysql union 2 查询
【发布时间】:2019-10-24 23:46:48
【问题描述】:

我有一个包含以下列的表格: id (AI), status (boolean 0 or 1), created at (datetime)

我想获取状态 = 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())

【问题讨论】:

  • bouhun.missions 中的列是什么?

标签: mysql random union


【解决方案1】:

UNION 集合运算符正在强制执行“使用文件排序”操作来识别和删除重复项。

UNION ALL 集合运算符将连接两个结果集,而不调用排序操作来识别和删除重复项。

但如果只是将UNION 替换为UNION ALL,我们将依赖于无法保证的行为。如果我们需要按特定顺序返回的结果,那么最外面的查询应该有一个ORDER BY 子句。

https://dev.mysql.com/doc/refman/8.0/en/union.html

摘录

但是,将ORDER BY 用于单个SELECT 语句并不意味着行在最终结果中出现的顺序,因为UNION 默认会生成一组无序的行。

...

(如果有人向其中一个表添加一列,这将导致此查询失败,返回的列数不匹配。)

(第二个 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

【讨论】:

  • 谢谢。这是完美的
【解决方案2】:

不久前我也遇到过类似的问题... 这样的事情应该可以解决它。

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 将为您提供您所需要的。 [请原谅我查询中的语法错误。]

【讨论】:

    猜你喜欢
    • 2011-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-03
    • 1970-01-01
    • 2014-05-30
    • 2016-11-22
    • 1970-01-01
    相关资源
    最近更新 更多