优先考虑 MySQL 中的辅助 ORDER BY 字段
Give priority to secondary ORDER BY field in MySQL
我一直在为 MySQL 查询而苦苦挣扎,但似乎找不到任何解决问题的方法。
我有一个文档数据库,我想按时间排序。很简单的。复杂情况如下:如果两个或多个文档在名为 correlation_id
的列中共享相同的值,我希望将它们并排放置。如果我简单地先按 correlation_id
排序,相关的行将放在顶部或底部。我希望将它们放在最近文档的位置。
举个例子,假设我有一个文档列表,文档 B
和 D
是 "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 列。但是为了理解我想我会显示它。
我一直在为 MySQL 查询而苦苦挣扎,但似乎找不到任何解决问题的方法。
我有一个文档数据库,我想按时间排序。很简单的。复杂情况如下:如果两个或多个文档在名为 correlation_id
的列中共享相同的值,我希望将它们并排放置。如果我简单地先按 correlation_id
排序,相关的行将放在顶部或底部。我希望将它们放在最近文档的位置。
举个例子,假设我有一个文档列表,文档 B
和 D
是 "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 列。但是为了理解我想我会显示它。