我需要获取同一张表上两个日期之间的所有值,而且还要包括最早的值之前的值:
更清楚地说,我有下表(表1.带有约4,600万行):
Table 1. (Table I have)
updatetime | value
. .
. .
2018-01-01 08:32:02 | 2
2018-01-01 09:23:12 | 5
2018-01-01 10:45:00 | 8 * value to include on the result.
2018-01-01 11:10:44 | 10 * <-- earliest date.
2018-01-01 13:11:54 | 12 *
2018-01-01 16:14:57 | 16 *
2018-01-01 20:00:55 | 22 *
2018-01-01 22:34:43 | 23 *
2018-01-01 23:55:23 | 23 * <-- latest date.
2018-01-02 01:03:57 | 25
2018-01-02 03:39:07 | 28
. .
. .
我有累加值,因此,下一个值将始终等于或大于之前的值。我需要获取2018年1月1日11:10:44和2018年1月2日01:03:57之间的所有值,但是,我还需要最早的日期之前的值,这意味着我需要此结果:(表2。)
Table 2. (Result I need)
2018-01-01 10:45:00 | 8
2018-01-01 11:10:44 | 10
2018-01-01 13:11:54 | 12
2018-01-01 16:14:57 | 16
2018-01-01 20:00:55 | 22
2018-01-01 22:34:43 | 23
2018-01-01 23:55:23 | 23
如表1所示,日期空间并不相同,因此最早的日期的先前日期对我来说是未知的,并且值的增加也是随机的。
我已经尝试了这两个查询,但是对性能有疑问:
第一个查询只是两个查询,由于表顺序的更改,因此性能很差。
SELECT * FROM his
WHERE updatetime>=(
SELECT updatetime
FROM definition
WHERE updatetime<"2018-01-01 11:10:44"
ORDER BY updatetime DESC
LIMIT 1
) and updatetime<="2018-01-02 01:03:57";
第二个应该比第一个慢,但是如果我将列定义为增量以使MySQL从条件的最后一个值开始遍历表而不是遍历整个条件?
SELECT * FROM his
WHERE updatetime>=(
SELECT MAX(updatetime)
FROM definition
WHERE updatetime<"2018-01-01 11:10:44"
LIMIT 1
) AND updatetime<="2018-01-02 01:03:57";
答案 0 :(得分:0)
首先,为了使这些查询有效执行,您需要在列updatetime
上建立索引:
CREATE INDEX idx_updatetime ON mytable(updatetime);
一种方法是在WHERE
子句中使用相关子查询来选择上一条记录:
SELECT t.*
FROM mytable t
WHERE
t.updatetime < '2018-01-02 01:03:57'
AND NOT EXISTS (
SELECT 1
FROM mytable t1
WHERE t1.updatetime < '2018-01-01 11:10:44' AND t1.updatetime > t.updatetime
)
| updatetime | value |
| ------------------- | ----- |
| 2018-01-01 11:10:44 | 10 |
| 2018-01-01 13:11:54 | 12 |
| 2018-01-01 16:14:57 | 16 |
| 2018-01-01 20:00:55 | 22 |
| 2018-01-01 22:34:43 | 23 |
| 2018-01-01 23:55:23 | 23 |
另一种选择是计算子查询中上一条记录的updatetime
,然后使用它来过滤表。该可能的性能要优于第一个查询。
SELECT t.*
FROM mytable t
INNER JOIN (
SELECT MAX(updatetime) updatetime
FROM mytable
WHERE updatetime < '2018-01-01 11:10:44'
) x ON t.updatetime >= x.updatetime AND t.updatetime < '2018-01-02 01:03:57';