在select where语句中扩展查询结果

时间:2019-02-08 22:10:05

标签: mysql sql

我需要获取同一张表上两个日期之间的所有值,而且还要包括最早的值之前的值:

更清楚地说,我有下表(表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";

1 个答案:

答案 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
    )

Demo on DB Fiddle

| 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';

Demo on DB Fiddle