优先考虑MySQL

时间:2018-02-20 15:18:09

标签: mysql sorting sql-order-by

我一直在努力使用MySQL查询,似乎我找不到任何问题的解决方案。

我有一个文件数据库,我想按时间订购。非常简单。复杂性如下:如果两个或多个文档在名为correlation_id的列中共享相同的值,我希望它们彼此相邻放置。如果我只是先按correlation_id排序,相关的行将放在顶部或底部。我希望将它们放在最新文档的位置。

例如,假设我有一个文档列表,文档BD与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时,表格主要按相关性排序,并给出:

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

提前谢谢。

1 个答案:

答案 0 :(得分:0)

Demo at Rextester以下两个答案。

支持在选择中使用选择...加入以获得最短时间,分组似乎更难以维护;并增加了混乱。因此,select in select可能更容易理解和维护,但从长远来看它应该更慢。

我们使用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

我认为另一种方法更快(更多的是你拥有的行......)但更难以理解/维护。

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,time的索引第二个查询更快的原因是因为它只需要进行一次连接。而第一个查询必须为文档中的每个记录执行子查询。因此,您可以看到查询的文档越多,查询就越慢。

第二个查询生成包含每个correlation_ID的最小时间的数据子集(MinCorT)。我们将基集连接到此集合,因此我们有每个文档的最小时间具有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列。但是为了理解,我以为我会展示它。