Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > MySQL > Выборка за несколько часов


Автор: s1lver 6.11.2015, 08:19
Доброго времени суток!

Подскажите пожалуйста, что-то я в затруднении. Необходимо выбрать записи за последние несколько часов. Беру, к примеру, 4 часа:

Код

SELECT `items`
FROM `units`
WHERE `meta` = ':meta'
AND `time` >= DATE_SUB(NOW(), INTERVAL 4 HOUR)


Запрос на небольшом количестве данных, работает отлично. Но стоит подсунуть, к примеру ~600 000 записей, то ищет вовсе не последние 4 часа (добавляет еще 3 часа или не добирает 1 час).  smile 

Аналогично работает и такой запрос:
Код

HOUR(TIMEDIFF(NOW(), `time`)) <= 4

Автор: Akina 6.11.2015, 08:55
Не верю.
Покажите DDL.

Автор: s1lver 6.11.2015, 09:03
Цитата(Akina @ 6.11.2015,  08:55)
Не верю.
Покажите DDL.

Код

sql> SELECT `items`
FROM `units`
WHERE `meta` = 'BLR'
AND `time` >= DATE_SUB(NOW(), INTERVAL 6 HOUR)
[2015-11-06 10:59:20] 164 rows retrieved starting from 1 in 236ms (execution: 218ms, fetching: 18ms)


Выбраны в итоге все записи, начиная, по времени, от последней за сегодня, до первой за сегодня. Т.е:
2015-11-06 01:59:50
2015-11-06 02:59:11
2015-11-06 03:58:18
2015-11-06 04:57:12
2015-11-06 05:51:42
2015-11-06 06:53:23
2015-11-06 07:59:26
2015-11-06 08:30:04

Забыл упомянуть, что meta(enum), time(datetime) и на оба поля созданы индексы.

Код

CREATE TABLE `units` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `items` decimal(12,3) DEFAULT NULL,
  `meta` enum('BLR','USP','ESP') COLLATE utf8_unicode_ci DEFAULT NULL,
  `time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `time_meta` (`meta`,`time`)
) ENGINE=InnoDB AUTO_INCREMENT=1502968 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

Автор: tzirechnoy 6.11.2015, 09:59
http://en.wikipedia.org/wiki/DDL, первая ссылка.

Автор: Akina 6.11.2015, 10:12
Не верю!

Код

mysql> CREATE TABLE units (
    -> items int,
    -> meta enum('BLR','OTHER'),
    -> `time` datetime
    -> );
Query OK, 0 rows affected (2.70 sec)

mysql> INSERT INTO units (`time`,meta,items)
    -> SELECT '2015-11-06  1:59:50','BLR',1 UNION ALL
    -> SELECT '2015-11-06  2:59:11','BLR',2 UNION ALL
    -> SELECT '2015-11-06  3:58:18','BLR',3 UNION ALL
    -> SELECT '2015-11-06  4:57:12','BLR',4 UNION ALL
    -> SELECT '2015-11-06  5:51:42','BLR',5 UNION ALL
    -> SELECT '2015-11-06  6:53:23','BLR',6 UNION ALL
    -> SELECT '2015-11-06  7:59:26','BLR',7 UNION ALL
    -> SELECT '2015-11-06  8:30:04','BLR',8 ;
Query OK, 8 rows affected (0.08 sec)
Records: 8  Duplicates: 0  Warnings: 0

mysql> select * from units;
+-------+------+---------------------+
| items | meta | time                |
+-------+------+---------------------+
|     1 | BLR  | 2015-11-06 01:59:50 |
|     2 | BLR  | 2015-11-06 02:59:11 |
|     3 | BLR  | 2015-11-06 03:58:18 |
|     4 | BLR  | 2015-11-06 04:57:12 |
|     5 | BLR  | 2015-11-06 05:51:42 |
|     6 | BLR  | 2015-11-06 06:53:23 |
|     7 | BLR  | 2015-11-06 07:59:26 |
|     8 | BLR  | 2015-11-06 08:30:04 |
+-------+------+---------------------+
8 rows in set (0.04 sec)

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2015-11-06 10:13:56 |
+---------------------+
1 row in set (0.00 sec)

mysql> select items
    -> from units
    -> where meta = 'BLR'
    -> and `time` >= date_sub(now(), interval 6 hour);
+-------+
| items |
+-------+
|     4 |
|     5 |
|     6 |
|     7 |
|     8 |
+-------+
5 rows in set (0.00 sec)

mysql>


Цитату с консоли в студию.
И DDL всё-таки.

Автор: s1lver 6.11.2015, 10:56
Цитата

Цитату с консоли в студию.


Так я же ее привел, вместе с DDL. 

Для 'BLR' при запросе 

Код

sql> SELECT `time`
FROM `units`
WHERE `meta` = 'BLR'
AND `time` >= DATE_SUB(NOW(), INTERVAL 6 HOUR)
[2015-11-06 12:54:11] 69 rows retrieved starting from 1 in 212ms (execution: 205ms, fetching: 7ms)


получаю
Код

2015-11-06 04:00:02
2015-11-06 04:00:44
2015-11-06 04:05:20
2015-11-06 04:06:51
2015-11-06 04:23:46
2015-11-06 04:33:10
2015-11-06 04:33:58
2015-11-06 04:38:16
2015-11-06 04:38:31
2015-11-06 04:41:17
2015-11-06 04:44:15
2015-11-06 04:44:29
2015-11-06 04:48:02
2015-11-06 04:52:12
2015-11-06 05:01:20
2015-11-06 05:03:25
2015-11-06 05:06:03
2015-11-06 05:10:41
2015-11-06 05:11:52
2015-11-06 05:43:15
2015-11-06 05:46:31
2015-11-06 05:52:28
2015-11-06 05:54:40
2015-11-06 05:55:42
2015-11-06 05:55:46
2015-11-06 05:56:58
2015-11-06 05:58:45
2015-11-06 06:00:16
2015-11-06 06:03:07
2015-11-06 06:14:59
2015-11-06 06:16:02
2015-11-06 06:20:15
2015-11-06 06:24:45
2015-11-06 07:09:59
2015-11-06 07:35:13
2015-11-06 07:39:10
2015-11-06 07:40:22
2015-11-06 07:44:04
2015-11-06 07:45:22
2015-11-06 07:53:25
2015-11-06 07:55:46
2015-11-06 08:14:04
2015-11-06 08:30:48
2015-11-06 08:34:45
2015-11-06 08:35:44
2015-11-06 08:40:32
2015-11-06 08:49:04
2015-11-06 08:49:46
2015-11-06 09:00:43
2015-11-06 09:03:23
2015-11-06 09:12:38
2015-11-06 09:13:05
2015-11-06 09:26:04
2015-11-06 09:28:20
2015-11-06 09:32:50
2015-11-06 09:35:02
2015-11-06 09:35:13
2015-11-06 09:37:23
2015-11-06 09:39:06
2015-11-06 09:39:43
2015-11-06 09:41:19
2015-11-06 09:50:06
2015-11-06 09:50:57
2015-11-06 09:59:10
2015-11-06 10:01:36
2015-11-06 10:31:27
2015-11-06 10:39:15
2015-11-06 10:41:22
2015-11-06 10:48:47



Время:

sql> SELECT NOW() FROM units
[2015-11-06 13:00:44] 500 rows retrieved starting from 1 in 385ms (execution: 352ms, fetching: 33ms)

2015-11-06 08:58:31

Время сервера: Fri Nov  6 08:58:58 CET 2015

Автор: Akina 6.11.2015, 11:00
Цитата(s1lver @  6.11.2015,  11:56 Найти цитируемый пост)
Так я же ее привел, вместе с DDL. 

Вы привели некие вырезки. Дайте полный необрезанный листинг, такой, как у меня. Есссно уменьшите интервал, чтобы записей поменьше было - одного-двух часов достаточно. И не забудьте SELECT NOW().

Добавлено через 1 минуту и 39 секунд
Хотя по тому, что я вижу - хочется предположить, что имеет место проблема с зоной времени (явно откуда-то плывёт девиация в 2 часа).

Автор: s1lver 6.11.2015, 11:29
Цитата

Дайте полный необрезанный листинг, такой, как у меня


Код

mysql> SELECT NOW();
+---------------------+
| NOW()               |
+---------------------+
| 2015-11-06 09:25:33 |
+---------------------+
1 row in set (0.00 sec)

mysql> SELECT `time` FROM `units` WHERE `meta` = 'BLR' AND `time` >= DATE_SUB(NOW(), INTERVAL 6 HOUR)
    -> ;
+---------------------+
| time                |
+---------------------+
| 2015-11-06 04:52:12 |
| 2015-11-06 05:58:45 |
| 2015-11-06 06:24:45 |
| 2015-11-06 07:55:46 |
| 2015-11-06 08:49:46 |
| 2015-11-06 09:59:10 |
| 2015-11-06 10:58:17 |
| 2015-11-06 11:20:29 |
+---------------------+
85 rows in set (0.00 sec)


Автор: Akina 6.11.2015, 12:06
Текущее время, если верить цитате консоли, 2015-11-06 09:25:33.
С учётом этого в соответствии с текстом запроса должны возвращаться все записи, в которых дата-время не ранее 2015-11-06 03:25:33.
Все процитированные записи этому условию соответствуют.
В чём проблема?

Автор: s1lver 6.11.2015, 12:16
Цитата

В чём проблема?


Кажется я где туплю очень сильно. Мне необходимо получить записи за последние 6 часов. А получаю за 8 или 9.

Т.е, если 2015-11-06 09:25:33, минимальное полученное время должно быть 2015-11-06 04:25:33. Соответственно, полагаю, что если время 2015-11-06 03:25:33, то минимальное время 2015-11-05 22:25:33


Так, можно, в принципе так поступить:

Код

`time` BETWEEN NOW() - INTERVAL 6 HOUR  AND NOW()

Автор: Akina 6.11.2015, 13:30
Цитата(s1lver @  6.11.2015,  13:16 Найти цитируемый пост)
если 2015-11-06 09:25:33, минимальное полученное время должно быть 2015-11-06 04:25:33.

Цитата(s1lver @  6.11.2015,  13:16 Найти цитируемый пост)
если время 2015-11-06 03:25:33, то минимальное время 2015-11-05 22:25:33

Если я хоть что-то понимаю в колбасных обрезках, то, отнимая от 9 часов с копейками 6 часов, мы должны получить 3 часа с теми же копейками. А никак не 4... И во втором случае 21 час, а не 22...

Код

mysql> SELECT '2015-11-06 09:25:33' - INTERVAL 6 HOUR,
    ->        '2015-11-06 03:25:33' - INTERVAL 6 HOUR;
+-----------------------------------------+-----------------------------------------+
| '2015-11-06 09:25:33' - INTERVAL 6 HOUR | '2015-11-06 03:25:33' - INTERVAL 6 HOUR |
+-----------------------------------------+-----------------------------------------+
| 2015-11-06 03:25:33                     | 2015-11-05 21:25:33                     |
+-----------------------------------------+-----------------------------------------+
1 row in set (0.00 sec)


Цитата(s1lver @  6.11.2015,  13:16 Найти цитируемый пост)
можно, в принципе так поступить:

Это совсем другое условие.
Согласно твоим данным в примере, у тебя есть записи "из будущего". В исходной постановке они возвращались, в этой возвращаться не будут.

Автор: s1lver 6.11.2015, 14:03
Цитата

В исходной постановке они возвращались, в этой возвращаться не будут. 


Так мне же и надо, от текущего времени отнять, допустим, 6 часов. И вот этот промежуток времени получить. Т.е промежуток в 6 часов от текущего времени. Получается, второе решение то, что надо  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)