Разверните результат запроса в операторе select where - PullRequest
0 голосов
/ 09 февраля 2019

Мне нужно получить все значения между двумя датами в одной и той же таблице, но также включить значение непосредственно перед самой ранней:

Для большей ясности у меня есть следующая таблица (Таблица 1.с приблизительно 46 миллионами строк):

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-01-01 11:10:44 и 2018-01-02 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 голосов
/ 09 февраля 2019

Прежде всего, чтобы эти запросы выполнялись эффективно, вам потребуется индекс для столбца 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
    )

Демонстрация на 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';

Демонстрация на DB Fiddle

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...