优先考虑 MySQL 中的辅助 ORDER BY 字段

Give priority to secondary ORDER BY field in MySQL

我一直在为 MySQL 查询而苦苦挣扎,但似乎找不到任何解决问题的方法。

我有一个文档数据库,我想按时间排序。很简单的。复杂情况如下:如果两个或多个文档在名为 correlation_id 的列中共享相同的值,我希望将它们并排放置。如果我简单地先按 correlation_id 排序,相关的行将放在顶部或底部。我希望将它们放在最近文档的位置。

举个例子,假设我有一个文档列表,文档 BD 是 "correlated" 和一个 id,只是它们在一列中共有的数字.

当我使用ORDER BY time时,输出是:

time          document          correlation_id
1h            A                 0
2h            B                 1
4h            C                 0
4h            D                 1
6h            E                 0

当我使用 ORDER BY correlation_id, time 时,table 主要按相关性排序,并给出:

time          document          correlation_id
2h            B                 1
4h            D                 1
1h            A                 0
4h            C                 0
6h            E                 0

我不想将相关项放在顶部或底部,而是放在最近文档的位置,所以它看起来像:

time          document          correlation_id
1h            A                 0
2h            B                 1
4h            D                 1
4h            C                 0
6h            E                 0

作为查询,它必须如下所示:

SELECT * FROM DOCUMENTS ORDER BY [if (correlation_id<>0) {order by correlation_id first}], time DESC

提前致谢。

Demo at Rextester 以下两个答案。

支持在select秒中使用select秒...获得最短时间的连接和分组似乎就像他们会更难维护一样;并增加了混乱。因此 select in select 可能更容易理解和维护,尽管它在 long 运行.

中应该更慢

我们使用 select 来获取每个非 0 的最短时间 correlation_ID;对于那些为零的,我们只使用记录时间。并合并这两个值,为我们提供一个 MinTime 列,然后我们可以先按时间排序,然后按时间排序以获得所需的排序。

SELECT BaseSet.*, coalesce((SELECT min(time) MT
             FROM DOCUMENTS MinCorT
             WHERE MinCorT.Correlation_ID = BaseSet.Correlation_ID
               and correlation_ID <> 0), time) MINTIME
FROM documents BaseSet
ORDER BY MINTIME, Time

我认为另一种方法更快(行数越多...)但更难 understand/maintain。

SELECT BaseSet.*, coalesce(MinCorT.MinTime, BasetSet.Time) MinTime
FROM documents BaseSet
LEFT JOIN (SELECT min(Time) MinTime, Correlation_ID
            FROM Documents MinCorT
            WHERE Correlation_ID <> 0 
            GROUP BY Correlation_Id) B
  on BaseSet.Correlation_ID = MinCorT.Correlation_ID
ORDER BY MinTime, time

第二个查询假定您在 correlation_ID 上有一个索引,时间 第二个查询会更快的原因是因为它只需要执行一次连接。而第一个查询必须对文档中的每条记录执行子查询。因此,您可以看到拥有的文档越多,查询速度就越慢。

第二个查询生成一个数据子集 (MinCorT),其中包含每个 correlation_ID 的最短时间。我们将基础集左连接到这个集,这样我们就有了每个文档的最短时间 correlation_ID。我们使用 coalesce 在 correlation_ID 为 0(无最小时间记录)的情况下使用基本文档时间。我们再次得到一个我们可以排序的 MinTime 列和一个时间列以产生所需的排序。

第二种方法代码较多,因此更难维护,但在长期 运行.

中应该具有更好的性能。

鉴于您的示例数据;两个查询的结果都是:

+------+----------+----------------+---------+
| Time | document | Correlation_ID | MinTime |
+------+----------+----------------+---------+
| 1h   | A        |              0 | 1h      |
| 2h   | B        |              1 | 2h      |
| 4h   | D        |              1 | 2h      |
| 4h   | C        |              0 | 4h      |
| 6h   | E        |              0 | 6h      |
+------+----------+----------------+---------+

尽管在第二个中我们可以将合并向下移动到排序依据并且根本没有 MinTime 列。但是为了理解我想我会显示它。